Literal Style / add support for a filter property
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
import {assign} from '../obj.js';
|
import {assign} from '../obj.js';
|
||||||
import WebGLPointsLayerRenderer from '../renderer/webgl/PointsLayer.js';
|
import WebGLPointsLayerRenderer from '../renderer/webgl/PointsLayer.js';
|
||||||
import {parseSymbolStyle} from '../webgl/ShaderBuilder.js';
|
import {parseLiteralStyle} from '../webgl/ShaderBuilder.js';
|
||||||
import Layer from './Layer.js';
|
import Layer from './Layer.js';
|
||||||
|
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ class WebGLPointsLayer extends Layer {
|
|||||||
* @private
|
* @private
|
||||||
* @type {import('../webgl/ShaderBuilder.js').StyleParseResult}
|
* @type {import('../webgl/ShaderBuilder.js').StyleParseResult}
|
||||||
*/
|
*/
|
||||||
this.parseResult_ = parseSymbolStyle(options.style.symbol);
|
this.parseResult_ = parseLiteralStyle(options.style);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -4,8 +4,41 @@
|
|||||||
* @module ol/style/LiteralStyle
|
* @module ol/style/LiteralStyle
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base type used for literal style parameters; can be a number literal or the output of an operator,
|
||||||
|
* which in turns takes {@link ExpressionValue} arguments.
|
||||||
|
*
|
||||||
|
* The following operators can be used:
|
||||||
|
*
|
||||||
|
* * Reading operators:
|
||||||
|
* * `['get', 'attributeName']` fetches a feature attribute (it will be prefixed by `a_` in the shader)
|
||||||
|
*
|
||||||
|
* * Math operators:
|
||||||
|
* * `['*', value1, value1]` multiplies value1 by value2
|
||||||
|
* * `['+', value1, value1]` adds value1 and value2
|
||||||
|
* * `['clamp', value1, value2, value3]` clamps value1 between values2 and value3
|
||||||
|
* * `['stretch', value1, value2, value3, value4, value5]` maps value1 from [value2, value3] range to
|
||||||
|
* [value4, value5] range, clamping values along the way
|
||||||
|
*
|
||||||
|
* * Logical operators:
|
||||||
|
* * `['<', value1, value2]` returns `1` if `value1` is strictly lower than value 2, or `0` otherwise.
|
||||||
|
* * `['<=', value1, value2]` returns `1` if `value1` is lower than or equals value 2, or `0` otherwise.
|
||||||
|
* * `['>', value1, value2]` returns `1` if `value1` is strictly greater than value 2, or `0` otherwise.
|
||||||
|
* * `['>=', value1, value2]` returns `1` if `value1` is greater than or equals value 2, or `0` otherwise.
|
||||||
|
* * `['==', value1, value2]` returns `1` if `value1` equals value 2, or `0` otherwise.
|
||||||
|
* * `['!', value1]` returns `0` if `value1` strictly greater than `0`, or `1` otherwise.
|
||||||
|
* * `['between', value1, value2, value3]` returns `1` if `value1` is contained between `value2` and `value3`
|
||||||
|
* (inclusively), or `0` otherwise.
|
||||||
|
*
|
||||||
|
* Values can either be literals (numbers) or another operator, as they will be evaluated recursively.
|
||||||
|
*
|
||||||
|
* @typedef {Array<*>|number} ExpressionValue
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} LiteralStyle
|
* @typedef {Object} LiteralStyle
|
||||||
|
* @property {ExpressionValue} [filter] Filter expression. If it resolves to a number strictly greater than 0, the
|
||||||
|
* point will be displayed. If undefined, all points will show.
|
||||||
* @property {LiteralSymbolStyle} [symbol] Symbol representation.
|
* @property {LiteralSymbolStyle} [symbol] Symbol representation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -22,12 +55,12 @@ export const SymbolType = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} LiteralSymbolStyle
|
* @typedef {Object} LiteralSymbolStyle
|
||||||
* @property {number|Array.<number, number>} size Size, mandatory.
|
* @property {ExpressionValue|Array<ExpressionValue, ExpressionValue>} size Size, mandatory.
|
||||||
* @property {SymbolType} symbolType Symbol type to use, either a regular shape or an image.
|
* @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 {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 {import("../color.js").Color|Array<ExpressionValue>|string} [color='#FFFFFF'] Color used for the representation (either fill, line or symbol).
|
||||||
* @property {number} [opacity=1] Opacity.
|
* @property {ExpressionValue} [opacity=1] Opacity.
|
||||||
* @property {Array.<number, number>} [offset] Offset on X and Y axis for symbols. If not specified, the symbol will be centered.
|
* @property {Array<ExpressionValue, ExpressionValue>} [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 {Array<ExpressionValue, ExpressionValue, ExpressionValue, ExpressionValue>} [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.
|
* @property {boolean} [rotateWithView=false] Specify whether the symbol must rotate with the view or stay upwards.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -37,32 +37,17 @@ export function formatColor(colorArray) {
|
|||||||
}).map(formatNumber).join(', ');
|
}).map(formatNumber).join(', ');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Base type for values fed to operators; can be a number literal or the output of another operator
|
|
||||||
* @typedef {Array<*>|number} OperatorValue
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the provided expressions and produces a GLSL-compatible assignment string, such as:
|
* Parses the provided expressions and produces a GLSL-compatible assignment string, such as:
|
||||||
* `['add', ['*', ['get', 'size'], 0.001], 12] => '(a_size * (0.001)) + (12.0)'
|
* `['add', ['*', ['get', 'size'], 0.001], 12] => '(a_size * (0.001)) + (12.0)'
|
||||||
*
|
*
|
||||||
* The following operators can be used:
|
|
||||||
* * `['get', 'attributeName']` fetches a feature attribute (it will be prefixed by `a_` in the shader)
|
|
||||||
* * `['*', value1, value1]` multiplies value1 by value2
|
|
||||||
* * `['+', value1, value1]` adds value1 and value2
|
|
||||||
* * `['clamp', value1, value2, value3]` clamps value1 between values2 and value3
|
|
||||||
* * `['stretch', value1, value2, value3, value4, value5]` maps value1 from [value2, value3] range to
|
|
||||||
* [value4, value5] range, clamping values along the way
|
|
||||||
*
|
|
||||||
* Values can either be literals (numbers) or another operator, as they will be evaluated recursively.
|
|
||||||
*
|
|
||||||
* Also takes in an array where new attributes will be pushed, so that the user of the `parse` function
|
* Also takes in an array where new attributes will be pushed, so that the user of the `parse` function
|
||||||
* knows which attributes are expected to be available at evaluation time.
|
* knows which attributes are expected to be available at evaluation time.
|
||||||
*
|
*
|
||||||
* A prefix must be specified so that the attributes can either be written as `a_name` or `v_name` in
|
* A prefix must be specified so that the attributes can either be written as `a_name` or `v_name` in
|
||||||
* the final assignment string.
|
* the final assignment string.
|
||||||
*
|
*
|
||||||
* @param {OperatorValue} value Either literal or an operator.
|
* @param {import("../style/LiteralStyle").ExpressionValue} value Either literal or an operator.
|
||||||
* @param {Array<string>} attributes Array containing the attribute names **without a prefix**;
|
* @param {Array<string>} attributes Array containing the attribute names **without a prefix**;
|
||||||
* it passed along recursively
|
* it passed along recursively
|
||||||
* @param {string} attributePrefix Prefix added to attribute names in the final output (typically `a_` or `v_`).
|
* @param {string} attributePrefix Prefix added to attribute names in the final output (typically `a_` or `v_`).
|
||||||
@@ -75,15 +60,31 @@ export function parse(value, attributes, attributePrefix) {
|
|||||||
}
|
}
|
||||||
if (Array.isArray(v)) {
|
if (Array.isArray(v)) {
|
||||||
switch (v[0]) {
|
switch (v[0]) {
|
||||||
|
// reading operators
|
||||||
case 'get':
|
case 'get':
|
||||||
if (attributes.indexOf(v[1]) === -1) {
|
if (attributes.indexOf(v[1]) === -1) {
|
||||||
attributes.push(v[1]);
|
attributes.push(v[1]);
|
||||||
}
|
}
|
||||||
return attributePrefix + v[1];
|
return attributePrefix + v[1];
|
||||||
|
|
||||||
|
// math operators
|
||||||
case '*': return `(${p(v[1])} * ${p(v[2])})`;
|
case '*': return `(${p(v[1])} * ${p(v[2])})`;
|
||||||
case '+': return `(${p(v[1])} + ${p(v[2])})`;
|
case '+': return `(${p(v[1])} + ${p(v[2])})`;
|
||||||
case 'clamp': return `clamp(${p(v[1])}, ${p(v[2])}, ${p(v[3])})`;
|
case 'clamp': return `clamp(${p(v[1])}, ${p(v[2])}, ${p(v[3])})`;
|
||||||
case 'stretch': return `(clamp(${p(v[1])}, ${p(v[2])}, ${p(v[3])}) * ((${p(v[5])} - ${p(v[4])}) / (${p(v[3])} - ${p(v[2])})) + ${p(v[4])})`;
|
case 'stretch': return `(clamp(${p(v[1])}, ${p(v[2])}, ${p(v[3])}) * ((${p(v[5])} - ${p(v[4])}) / (${p(v[3])} - ${p(v[2])})) + ${p(v[4])})`;
|
||||||
|
|
||||||
|
// logical operators
|
||||||
|
case '>':
|
||||||
|
case '>=':
|
||||||
|
case '<':
|
||||||
|
case '<=':
|
||||||
|
case '==':
|
||||||
|
return `(${p(v[1])} ${v[0]} ${p(v[2])} ? 1.0 : 0.0)`;
|
||||||
|
case '!':
|
||||||
|
return `(${p(v[1])} > 0.0 ? 0.0 : 1.0)`;
|
||||||
|
case 'between':
|
||||||
|
return `(${p(v[1])} >= ${p(v[2])} && ${p(v[1])} <= ${p(v[3])} ? 1.0 : 0.0)`;
|
||||||
|
|
||||||
default: throw new Error('Unrecognized literal style expression: ' + JSON.stringify(value));
|
default: throw new Error('Unrecognized literal style expression: ' + JSON.stringify(value));
|
||||||
}
|
}
|
||||||
} else if (typeof value === 'number') {
|
} else if (typeof value === 'number') {
|
||||||
@@ -273,7 +274,7 @@ export class ShaderBuilder {
|
|||||||
* @return {ShaderBuilder} the builder object
|
* @return {ShaderBuilder} the builder object
|
||||||
*/
|
*/
|
||||||
setFragmentDiscardExpression(expression) {
|
setFragmentDiscardExpression(expression) {
|
||||||
this.texCoordExpression = expression;
|
this.discardExpression = expression;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -416,27 +417,28 @@ void main(void) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a {@link import("../style/LiteralStyle").LiteralSymbolStyle} object and returns a {@link ShaderBuilder}
|
* Parses a {@link import("../style/LiteralStyle").LiteralStyle} object and returns a {@link ShaderBuilder}
|
||||||
* object that has been configured according to the given style, as well as `attributes` and `uniforms`
|
* object that has been configured according to the given style, as well as `attributes` and `uniforms`
|
||||||
* arrays to be fed to the `WebGLPointsRenderer` class.
|
* arrays to be fed to the `WebGLPointsRenderer` class.
|
||||||
*
|
*
|
||||||
* Also returns `uniforms` and `attributes` properties as expected by the
|
* Also returns `uniforms` and `attributes` properties as expected by the
|
||||||
* {@link module:ol/renderer/webgl/PointsLayer~WebGLPointsLayerRenderer}.
|
* {@link module:ol/renderer/webgl/PointsLayer~WebGLPointsLayerRenderer}.
|
||||||
*
|
*
|
||||||
* @param {import("../style/LiteralStyle").LiteralSymbolStyle} style Symbol style.
|
* @param {import("../style/LiteralStyle").LiteralStyle} style Literal style.
|
||||||
* @returns {StyleParseResult} Result containing shader params, attributes and uniforms.
|
* @returns {StyleParseResult} Result containing shader params, attributes and uniforms.
|
||||||
*/
|
*/
|
||||||
export function parseSymbolStyle(style) {
|
export function parseLiteralStyle(style) {
|
||||||
const size = Array.isArray(style.size) && typeof style.size[0] == 'number' ?
|
const symbStyle = style.symbol;
|
||||||
style.size : [style.size, style.size];
|
const size = Array.isArray(symbStyle.size) && typeof symbStyle.size[0] == 'number' ?
|
||||||
const color = (typeof style.color === 'string' ?
|
symbStyle.size : [symbStyle.size, symbStyle.size];
|
||||||
asArray(style.color).map(function(c, i) {
|
const color = (typeof symbStyle.color === 'string' ?
|
||||||
|
asArray(symbStyle.color).map(function(c, i) {
|
||||||
return i < 3 ? c / 255 : c;
|
return i < 3 ? c / 255 : c;
|
||||||
}) :
|
}) :
|
||||||
style.color || [255, 255, 255, 1]);
|
symbStyle.color || [255, 255, 255, 1]);
|
||||||
const texCoord = style.textureCoord || [0, 0, 1, 1];
|
const texCoord = symbStyle.textureCoord || [0, 0, 1, 1];
|
||||||
const offset = style.offset || [0, 0];
|
const offset = symbStyle.offset || [0, 0];
|
||||||
const opacity = style.opacity !== undefined ? style.opacity : 1;
|
const opacity = symbStyle.opacity !== undefined ? symbStyle.opacity : 1;
|
||||||
|
|
||||||
const vertAttributes = [];
|
const vertAttributes = [];
|
||||||
// parse function for vertex shader
|
// parse function for vertex shader
|
||||||
@@ -452,7 +454,7 @@ export function parseSymbolStyle(style) {
|
|||||||
|
|
||||||
let opacityFilter = '1.0';
|
let opacityFilter = '1.0';
|
||||||
const visibleSize = pFrag(size[0]);
|
const visibleSize = pFrag(size[0]);
|
||||||
switch (style.symbolType) {
|
switch (symbStyle.symbolType) {
|
||||||
case 'square': break;
|
case 'square': break;
|
||||||
case 'image': break;
|
case 'image': break;
|
||||||
// taken from https://thebookofshaders.com/07/
|
// taken from https://thebookofshaders.com/07/
|
||||||
@@ -465,7 +467,7 @@ export function parseSymbolStyle(style) {
|
|||||||
opacityFilter = `(1.0-smoothstep(.5-3./${visibleSize},.5,cos(floor(.5+${a}/2.094395102)*2.094395102-${a})*length(${st})))`;
|
opacityFilter = `(1.0-smoothstep(.5-3./${visibleSize},.5,cos(floor(.5+${a}/2.094395102)*2.094395102-${a})*length(${st})))`;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: throw new Error('Unexpected symbol type: ' + style.symbolType);
|
default: throw new Error('Unexpected symbol type: ' + symbStyle.symbolType);
|
||||||
}
|
}
|
||||||
|
|
||||||
const builder = new ShaderBuilder()
|
const builder = new ShaderBuilder()
|
||||||
@@ -473,9 +475,13 @@ export function parseSymbolStyle(style) {
|
|||||||
.setSymbolOffsetExpression(`vec2(${pVert(offset[0])}, ${pVert(offset[1])})`)
|
.setSymbolOffsetExpression(`vec2(${pVert(offset[0])}, ${pVert(offset[1])})`)
|
||||||
.setTextureCoordinateExpression(
|
.setTextureCoordinateExpression(
|
||||||
`vec4(${pVert(texCoord[0])}, ${pVert(texCoord[1])}, ${pVert(texCoord[2])}, ${pVert(texCoord[3])})`)
|
`vec4(${pVert(texCoord[0])}, ${pVert(texCoord[1])}, ${pVert(texCoord[2])}, ${pVert(texCoord[3])})`)
|
||||||
.setSymbolRotateWithView(!!style.rotateWithView)
|
.setSymbolRotateWithView(!!symbStyle.rotateWithView)
|
||||||
.setColorExpression(`vec4(${pFrag(color[0])}, ${pFrag(color[1])}, ${pFrag(color[2])}, ${pFrag(color[3])})` +
|
.setColorExpression(
|
||||||
` * vec4(1.0, 1.0, 1.0, ${pFrag(opacity)} * ${opacityFilter})`);
|
`vec4(${pFrag(color[0])}, ${pFrag(color[1])}, ${pFrag(color[2])}, ${pFrag(color[3])} * ${pFrag(opacity)} * ${opacityFilter})`);
|
||||||
|
|
||||||
|
if (style.filter) {
|
||||||
|
builder.setFragmentDiscardExpression(`${pFrag(style.filter)} <= 0.0`);
|
||||||
|
}
|
||||||
|
|
||||||
// for each feature attribute used in the fragment shader, define a varying that will be used to pass data
|
// for each feature attribute used in the fragment shader, define a varying that will be used to pass data
|
||||||
// from the vertex to the fragment shader, as well as an attribute in the vertex shader (if not already present)
|
// from the vertex to the fragment shader, as well as an attribute in the vertex shader (if not already present)
|
||||||
@@ -491,13 +497,12 @@ export function parseSymbolStyle(style) {
|
|||||||
builder.addAttribute(`float a_${attrName}`);
|
builder.addAttribute(`float a_${attrName}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
/** @type {Object.<string,import("../webgl/Helper").UniformValue>} */
|
/** @type {Object.<string,import("../webgl/Helper").UniformValue>} */
|
||||||
const uniforms = {};
|
const uniforms = {};
|
||||||
|
|
||||||
if (style.symbolType === 'image' && style.src) {
|
if (symbStyle.symbolType === 'image' && symbStyle.src) {
|
||||||
const texture = new Image();
|
const texture = new Image();
|
||||||
texture.src = style.src;
|
texture.src = symbStyle.src;
|
||||||
builder.addUniform('sampler2D u_texture')
|
builder.addUniform('sampler2D u_texture')
|
||||||
.setColorExpression(builder.getColorExpression() +
|
.setColorExpression(builder.getColorExpression() +
|
||||||
' * texture2D(u_texture, v_texCoord)');
|
' * texture2D(u_texture, v_texCoord)');
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {
|
|||||||
formatColor,
|
formatColor,
|
||||||
formatNumber,
|
formatNumber,
|
||||||
parse,
|
parse,
|
||||||
parseSymbolStyle,
|
parseLiteralStyle,
|
||||||
ShaderBuilder
|
ShaderBuilder
|
||||||
} from '../../../../src/ol/webgl/ShaderBuilder.js';
|
} from '../../../../src/ol/webgl/ShaderBuilder.js';
|
||||||
|
|
||||||
@@ -212,7 +212,14 @@ void main(void) {
|
|||||||
expect(parseFn(['+', ['*', ['get', 'size'], 0.001], 12])).to.eql('((a_size * 0.001) + 12.0)');
|
expect(parseFn(['+', ['*', ['get', 'size'], 0.001], 12])).to.eql('((a_size * 0.001) + 12.0)');
|
||||||
expect(parseFn(['clamp', ['get', 'attr2'], ['get', 'attr3'], 20])).to.eql('clamp(a_attr2, a_attr3, 20.0)');
|
expect(parseFn(['clamp', ['get', 'attr2'], ['get', 'attr3'], 20])).to.eql('clamp(a_attr2, a_attr3, 20.0)');
|
||||||
expect(parseFn(['stretch', ['get', 'size'], 10, 100, 4, 8])).to.eql('(clamp(a_size, 10.0, 100.0) * ((8.0 - 4.0) / (100.0 - 10.0)) + 4.0)');
|
expect(parseFn(['stretch', ['get', 'size'], 10, 100, 4, 8])).to.eql('(clamp(a_size, 10.0, 100.0) * ((8.0 - 4.0) / (100.0 - 10.0)) + 4.0)');
|
||||||
expect(attributes).to.eql(['myAttr', 'size', 'attr2', 'attr3']);
|
expect(parseFn(['>', 10, ['get', 'attr4']])).to.eql('(10.0 > a_attr4 ? 1.0 : 0.0)');
|
||||||
|
expect(parseFn(['>=', 10, ['get', 'attr4']])).to.eql('(10.0 >= a_attr4 ? 1.0 : 0.0)');
|
||||||
|
expect(parseFn(['<', 10, ['get', 'attr4']])).to.eql('(10.0 < a_attr4 ? 1.0 : 0.0)');
|
||||||
|
expect(parseFn(['<=', 10, ['get', 'attr4']])).to.eql('(10.0 <= a_attr4 ? 1.0 : 0.0)');
|
||||||
|
expect(parseFn(['==', 10, ['get', 'attr4']])).to.eql('(10.0 == a_attr4 ? 1.0 : 0.0)');
|
||||||
|
expect(parseFn(['between', ['get', 'attr4'], -4.0, 5.0])).to.eql('(a_attr4 >= -4.0 && a_attr4 <= 5.0 ? 1.0 : 0.0)');
|
||||||
|
expect(parseFn(['!', ['get', 'attr4']])).to.eql('(a_attr4 > 0.0 ? 0.0 : 1.0)');
|
||||||
|
expect(attributes).to.eql(['myAttr', 'size', 'attr2', 'attr3', 'attr4']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not register an attribute several times', function() {
|
it('does not register an attribute several times', function() {
|
||||||
@@ -224,17 +231,19 @@ void main(void) {
|
|||||||
|
|
||||||
describe('parseSymbolStyle', function() {
|
describe('parseSymbolStyle', function() {
|
||||||
it('parses a style without expressions', function() {
|
it('parses a style without expressions', function() {
|
||||||
const result = parseSymbolStyle({
|
const result = parseLiteralStyle({
|
||||||
|
symbol: {
|
||||||
symbolType: 'square',
|
symbolType: 'square',
|
||||||
size: [4, 8],
|
size: [4, 8],
|
||||||
color: '#336699',
|
color: '#336699',
|
||||||
rotateWithView: true
|
rotateWithView: true
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result.builder.uniforms).to.eql([]);
|
expect(result.builder.uniforms).to.eql([]);
|
||||||
expect(result.builder.attributes).to.eql([]);
|
expect(result.builder.attributes).to.eql([]);
|
||||||
expect(result.builder.varyings).to.eql([]);
|
expect(result.builder.varyings).to.eql([]);
|
||||||
expect(result.builder.colorExpression).to.eql('vec4(0.2, 0.4, 0.6, 1.0) * vec4(1.0, 1.0, 1.0, 1.0 * 1.0)');
|
expect(result.builder.colorExpression).to.eql('vec4(0.2, 0.4, 0.6, 1.0 * 1.0 * 1.0)');
|
||||||
expect(result.builder.sizeExpression).to.eql('vec2(4.0, 8.0)');
|
expect(result.builder.sizeExpression).to.eql('vec2(4.0, 8.0)');
|
||||||
expect(result.builder.offsetExpression).to.eql('vec2(0.0, 0.0)');
|
expect(result.builder.offsetExpression).to.eql('vec2(0.0, 0.0)');
|
||||||
expect(result.builder.texCoordExpression).to.eql('vec4(0.0, 0.0, 1.0, 1.0)');
|
expect(result.builder.texCoordExpression).to.eql('vec4(0.0, 0.0, 1.0, 1.0)');
|
||||||
@@ -244,7 +253,8 @@ void main(void) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('parses a style with expressions', function() {
|
it('parses a style with expressions', function() {
|
||||||
const result = parseSymbolStyle({
|
const result = parseLiteralStyle({
|
||||||
|
symbol: {
|
||||||
symbolType: 'square',
|
symbolType: 'square',
|
||||||
size: ['get', 'attr1'],
|
size: ['get', 'attr1'],
|
||||||
color: [
|
color: [
|
||||||
@@ -252,6 +262,7 @@ void main(void) {
|
|||||||
],
|
],
|
||||||
textureCoord: [0.5, 0.5, 0.5, 1],
|
textureCoord: [0.5, 0.5, 0.5, 1],
|
||||||
offset: [3, ['get', 'attr3']]
|
offset: [3, ['get', 'attr3']]
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result.builder.uniforms).to.eql([]);
|
expect(result.builder.uniforms).to.eql([]);
|
||||||
@@ -266,7 +277,7 @@ void main(void) {
|
|||||||
expression: 'a_attr2'
|
expression: 'a_attr2'
|
||||||
}]);
|
}]);
|
||||||
expect(result.builder.colorExpression).to.eql(
|
expect(result.builder.colorExpression).to.eql(
|
||||||
'vec4(1.0, 0.0, 0.5, v_attr2) * vec4(1.0, 1.0, 1.0, 1.0 * 1.0)');
|
'vec4(1.0, 0.0, 0.5, v_attr2 * 1.0 * 1.0)');
|
||||||
expect(result.builder.sizeExpression).to.eql('vec2(a_attr1, a_attr1)');
|
expect(result.builder.sizeExpression).to.eql('vec2(a_attr1, a_attr1)');
|
||||||
expect(result.builder.offsetExpression).to.eql('vec2(3.0, a_attr3)');
|
expect(result.builder.offsetExpression).to.eql('vec2(3.0, a_attr3)');
|
||||||
expect(result.builder.texCoordExpression).to.eql('vec4(0.5, 0.5, 0.5, 1.0)');
|
expect(result.builder.texCoordExpression).to.eql('vec4(0.5, 0.5, 0.5, 1.0)');
|
||||||
@@ -279,19 +290,21 @@ void main(void) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('parses a style with a uniform (texture)', function() {
|
it('parses a style with a uniform (texture)', function() {
|
||||||
const result = parseSymbolStyle({
|
const result = parseLiteralStyle({
|
||||||
|
symbol: {
|
||||||
symbolType: 'image',
|
symbolType: 'image',
|
||||||
src: '../data/image.png',
|
src: '../data/image.png',
|
||||||
size: 6,
|
size: 6,
|
||||||
color: '#336699',
|
color: '#336699',
|
||||||
opacity: 0.5
|
opacity: 0.5
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result.builder.uniforms).to.eql(['sampler2D u_texture']);
|
expect(result.builder.uniforms).to.eql(['sampler2D u_texture']);
|
||||||
expect(result.builder.attributes).to.eql([]);
|
expect(result.builder.attributes).to.eql([]);
|
||||||
expect(result.builder.varyings).to.eql([]);
|
expect(result.builder.varyings).to.eql([]);
|
||||||
expect(result.builder.colorExpression).to.eql(
|
expect(result.builder.colorExpression).to.eql(
|
||||||
'vec4(0.2, 0.4, 0.6, 1.0) * vec4(1.0, 1.0, 1.0, 0.5 * 1.0) * texture2D(u_texture, v_texCoord)');
|
'vec4(0.2, 0.4, 0.6, 1.0 * 0.5 * 1.0) * texture2D(u_texture, v_texCoord)');
|
||||||
expect(result.builder.sizeExpression).to.eql('vec2(6.0, 6.0)');
|
expect(result.builder.sizeExpression).to.eql('vec2(6.0, 6.0)');
|
||||||
expect(result.builder.offsetExpression).to.eql('vec2(0.0, 0.0)');
|
expect(result.builder.offsetExpression).to.eql('vec2(0.0, 0.0)');
|
||||||
expect(result.builder.texCoordExpression).to.eql('vec4(0.0, 0.0, 1.0, 1.0)');
|
expect(result.builder.texCoordExpression).to.eql('vec4(0.0, 0.0, 1.0, 1.0)');
|
||||||
@@ -299,6 +312,32 @@ void main(void) {
|
|||||||
expect(result.attributes).to.eql([]);
|
expect(result.attributes).to.eql([]);
|
||||||
expect(result.uniforms).to.have.property('u_texture');
|
expect(result.uniforms).to.have.property('u_texture');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('parses a style with a filter', function() {
|
||||||
|
const result = parseLiteralStyle({
|
||||||
|
filter: ['between', ['get', 'attr0'], 0, 10],
|
||||||
|
symbol: {
|
||||||
|
symbolType: 'square',
|
||||||
|
size: 6,
|
||||||
|
color: '#336699'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result.builder.attributes).to.eql(['float a_attr0']);
|
||||||
|
expect(result.builder.varyings).to.eql([{
|
||||||
|
name: 'v_attr0',
|
||||||
|
type: 'float',
|
||||||
|
expression: 'a_attr0'
|
||||||
|
}]);
|
||||||
|
expect(result.builder.colorExpression).to.eql('vec4(0.2, 0.4, 0.6, 1.0 * 1.0 * 1.0)');
|
||||||
|
expect(result.builder.sizeExpression).to.eql('vec2(6.0, 6.0)');
|
||||||
|
expect(result.builder.offsetExpression).to.eql('vec2(0.0, 0.0)');
|
||||||
|
expect(result.builder.texCoordExpression).to.eql('vec4(0.0, 0.0, 1.0, 1.0)');
|
||||||
|
expect(result.builder.discardExpression).to.eql('(v_attr0 >= 0.0 && v_attr0 <= 10.0 ? 1.0 : 0.0) <= 0.0');
|
||||||
|
expect(result.builder.rotateWithView).to.eql(false);
|
||||||
|
expect(result.attributes.length).to.eql(1);
|
||||||
|
expect(result.attributes[0].name).to.eql('attr0');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user