Shader builder / add circle and triangle shapes for symbols
This commit is contained in:
@@ -15,6 +15,7 @@ const vector = new WebGLPointsLayer({
|
|||||||
}),
|
}),
|
||||||
style: {
|
style: {
|
||||||
symbol: {
|
symbol: {
|
||||||
|
symbolType: 'square',
|
||||||
size: 4,
|
size: 4,
|
||||||
color: 'white'
|
color: 'white'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,9 @@ export function formatColor(colorArray) {
|
|||||||
* The following attributes are hardcoded and expected to be present in the vertex buffers:
|
* The following attributes are hardcoded and expected to be present in the vertex buffers:
|
||||||
* `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).
|
||||||
*
|
*
|
||||||
|
* The following varyings are hardcoded and gives the coordinate of the pixel both in the quad on the texture:
|
||||||
|
* `vec2 v_quadCoord`, `vec2 v_texCoord`
|
||||||
|
*
|
||||||
* @param {ShaderParameters} parameters Parameters for the shader.
|
* @param {ShaderParameters} parameters Parameters for the shader.
|
||||||
* @returns {string} The full shader as a string.
|
* @returns {string} The full shader as a string.
|
||||||
*/
|
*/
|
||||||
@@ -92,6 +95,7 @@ ${attributes.map(function(attribute) {
|
|||||||
return 'attribute ' + attribute + ';';
|
return 'attribute ' + attribute + ';';
|
||||||
}).join('\n')}
|
}).join('\n')}
|
||||||
varying vec2 v_texCoord;
|
varying vec2 v_texCoord;
|
||||||
|
varying vec2 v_quadCoord;
|
||||||
${varyings.map(function(varying) {
|
${varyings.map(function(varying) {
|
||||||
return 'varying ' + varying.type + ' ' + varying.name + ';';
|
return 'varying ' + varying.type + ' ' + varying.name + ';';
|
||||||
}).join('\n')}
|
}).join('\n')}
|
||||||
@@ -107,6 +111,9 @@ void main(void) {
|
|||||||
float u = a_index == 0.0 || a_index == 3.0 ? texCoord.s : texCoord.q;
|
float u = a_index == 0.0 || a_index == 3.0 ? texCoord.s : texCoord.q;
|
||||||
float v = a_index == 2.0 || a_index == 3.0 ? texCoord.t : texCoord.p;
|
float v = a_index == 2.0 || a_index == 3.0 ? texCoord.t : texCoord.p;
|
||||||
v_texCoord = vec2(u, v);
|
v_texCoord = vec2(u, v);
|
||||||
|
u = a_index == 0.0 || a_index == 3.0 ? 0.0 : 1.0;
|
||||||
|
v = a_index == 2.0 || a_index == 3.0 ? 0.0 : 1.0;
|
||||||
|
v_quadCoord = vec2(u, v);
|
||||||
${varyings.map(function(varying) {
|
${varyings.map(function(varying) {
|
||||||
return ' ' + varying.name + ' = ' + varying.expression + ';';
|
return ' ' + varying.name + ' = ' + varying.expression + ';';
|
||||||
}).join('\n')}
|
}).join('\n')}
|
||||||
@@ -133,6 +140,7 @@ ${uniforms.map(function(uniform) {
|
|||||||
return 'uniform ' + uniform + ';';
|
return 'uniform ' + uniform + ';';
|
||||||
}).join('\n')}
|
}).join('\n')}
|
||||||
varying vec2 v_texCoord;
|
varying vec2 v_texCoord;
|
||||||
|
varying vec2 v_quadCoord;
|
||||||
${varyings.map(function(varying) {
|
${varyings.map(function(varying) {
|
||||||
return 'varying ' + varying.type + ' ' + varying.name + ';';
|
return 'varying ' + varying.type + ' ' + varying.name + ';';
|
||||||
}).join('\n')}
|
}).join('\n')}
|
||||||
@@ -236,10 +244,29 @@ export function parseSymbolStyle(style) {
|
|||||||
return parse(value, varyings, 'v_');
|
return parse(value, varyings, 'v_');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let opacityFilter = '1.0';
|
||||||
|
const visibleSize = pV(size[0]);
|
||||||
|
switch (style.symbolType) {
|
||||||
|
case 'square': break;
|
||||||
|
case 'image': break;
|
||||||
|
// taken from https://thebookofshaders.com/07/
|
||||||
|
case 'circle':
|
||||||
|
opacityFilter = `(1.0-smoothstep(1.-4./${visibleSize},1.,dot(v_quadCoord-.5,v_quadCoord-.5)*4.))`;
|
||||||
|
break;
|
||||||
|
case 'triangle':
|
||||||
|
const st = '(v_quadCoord*2.-1.)';
|
||||||
|
const a = `(atan(${st}.x,${st}.y))`;
|
||||||
|
opacityFilter = `(1.0-smoothstep(.5-3./${visibleSize},.5,cos(floor(.5+${a}/2.094395102)*2.094395102-${a})*length(${st})))`;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: throw new Error('Unexpected symbol type: ' + style.symbolType);
|
||||||
|
}
|
||||||
|
|
||||||
/** @type {import('../webgl/ShaderBuilder.js').ShaderParameters} */
|
/** @type {import('../webgl/ShaderBuilder.js').ShaderParameters} */
|
||||||
const params = {
|
const params = {
|
||||||
uniforms: [],
|
uniforms: [],
|
||||||
colorExpression: `vec4(${pV(color[0])}, ${pV(color[1])}, ${pV(color[2])}, ${pV(color[3])}) * vec4(1.0, 1.0, 1.0, ${pV(opacity)})`,
|
colorExpression: `vec4(${pV(color[0])}, ${pV(color[1])}, ${pV(color[2])}, ${pV(color[3])})` +
|
||||||
|
` * vec4(1.0, 1.0, 1.0, ${pV(opacity)} * ${opacityFilter})`,
|
||||||
sizeExpression: `vec2(${pA(size[0])}, ${pA(size[1])})`,
|
sizeExpression: `vec2(${pA(size[0])}, ${pA(size[1])})`,
|
||||||
offsetExpression: `vec2(${pA(offset[0])}, ${pA(offset[1])})`,
|
offsetExpression: `vec2(${pA(offset[0])}, ${pA(offset[1])})`,
|
||||||
texCoordExpression: `vec4(${pA(texCoord[0])}, ${pA(texCoord[1])}, ${pA(texCoord[2])}, ${pA(texCoord[3])})`,
|
texCoordExpression: `vec4(${pA(texCoord[0])}, ${pA(texCoord[1])}, ${pA(texCoord[2])}, ${pA(texCoord[3])})`,
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ attribute vec2 a_position;
|
|||||||
attribute float a_index;
|
attribute float a_index;
|
||||||
|
|
||||||
varying vec2 v_texCoord;
|
varying vec2 v_texCoord;
|
||||||
|
varying vec2 v_quadCoord;
|
||||||
varying float v_opacity;
|
varying float v_opacity;
|
||||||
varying vec3 v_test;
|
varying vec3 v_test;
|
||||||
void main(void) {
|
void main(void) {
|
||||||
@@ -71,6 +72,9 @@ void main(void) {
|
|||||||
float u = a_index == 0.0 || a_index == 3.0 ? texCoord.s : texCoord.q;
|
float u = a_index == 0.0 || a_index == 3.0 ? texCoord.s : texCoord.q;
|
||||||
float v = a_index == 2.0 || a_index == 3.0 ? texCoord.t : texCoord.p;
|
float v = a_index == 2.0 || a_index == 3.0 ? texCoord.t : texCoord.p;
|
||||||
v_texCoord = vec2(u, v);
|
v_texCoord = vec2(u, v);
|
||||||
|
u = a_index == 0.0 || a_index == 3.0 ? 0.0 : 1.0;
|
||||||
|
v = a_index == 2.0 || a_index == 3.0 ? 0.0 : 1.0;
|
||||||
|
v_quadCoord = vec2(u, v);
|
||||||
v_opacity = 0.4;
|
v_opacity = 0.4;
|
||||||
v_test = vec3(1.0, 2.0, 3.0);
|
v_test = vec3(1.0, 2.0, 3.0);
|
||||||
}`);
|
}`);
|
||||||
@@ -94,6 +98,7 @@ attribute vec2 a_position;
|
|||||||
attribute float a_index;
|
attribute float a_index;
|
||||||
attribute vec2 a_myAttr;
|
attribute vec2 a_myAttr;
|
||||||
varying vec2 v_texCoord;
|
varying vec2 v_texCoord;
|
||||||
|
varying vec2 v_quadCoord;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
mat4 offsetMatrix = u_offsetScaleMatrix;
|
mat4 offsetMatrix = u_offsetScaleMatrix;
|
||||||
@@ -107,6 +112,9 @@ void main(void) {
|
|||||||
float u = a_index == 0.0 || a_index == 3.0 ? texCoord.s : texCoord.q;
|
float u = a_index == 0.0 || a_index == 3.0 ? texCoord.s : texCoord.q;
|
||||||
float v = a_index == 2.0 || a_index == 3.0 ? texCoord.t : texCoord.p;
|
float v = a_index == 2.0 || a_index == 3.0 ? texCoord.t : texCoord.p;
|
||||||
v_texCoord = vec2(u, v);
|
v_texCoord = vec2(u, v);
|
||||||
|
u = a_index == 0.0 || a_index == 3.0 ? 0.0 : 1.0;
|
||||||
|
v = a_index == 2.0 || a_index == 3.0 ? 0.0 : 1.0;
|
||||||
|
v_quadCoord = vec2(u, v);
|
||||||
|
|
||||||
}`);
|
}`);
|
||||||
});
|
});
|
||||||
@@ -128,6 +136,7 @@ attribute vec2 a_position;
|
|||||||
attribute float a_index;
|
attribute float a_index;
|
||||||
|
|
||||||
varying vec2 v_texCoord;
|
varying vec2 v_texCoord;
|
||||||
|
varying vec2 v_quadCoord;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
mat4 offsetMatrix = u_offsetScaleMatrix * u_offsetRotateMatrix;
|
mat4 offsetMatrix = u_offsetScaleMatrix * u_offsetRotateMatrix;
|
||||||
@@ -141,6 +150,9 @@ void main(void) {
|
|||||||
float u = a_index == 0.0 || a_index == 3.0 ? texCoord.s : texCoord.q;
|
float u = a_index == 0.0 || a_index == 3.0 ? texCoord.s : texCoord.q;
|
||||||
float v = a_index == 2.0 || a_index == 3.0 ? texCoord.t : texCoord.p;
|
float v = a_index == 2.0 || a_index == 3.0 ? texCoord.t : texCoord.p;
|
||||||
v_texCoord = vec2(u, v);
|
v_texCoord = vec2(u, v);
|
||||||
|
u = a_index == 0.0 || a_index == 3.0 ? 0.0 : 1.0;
|
||||||
|
v = a_index == 2.0 || a_index == 3.0 ? 0.0 : 1.0;
|
||||||
|
v_quadCoord = vec2(u, v);
|
||||||
|
|
||||||
}`);
|
}`);
|
||||||
});
|
});
|
||||||
@@ -168,6 +180,7 @@ void main(void) {
|
|||||||
expect(getSymbolFragmentShader(parameters)).to.eql(`precision mediump float;
|
expect(getSymbolFragmentShader(parameters)).to.eql(`precision mediump float;
|
||||||
|
|
||||||
varying vec2 v_texCoord;
|
varying vec2 v_texCoord;
|
||||||
|
varying vec2 v_quadCoord;
|
||||||
varying float v_opacity;
|
varying float v_opacity;
|
||||||
varying vec3 v_test;
|
varying vec3 v_test;
|
||||||
void main(void) {
|
void main(void) {
|
||||||
@@ -188,6 +201,7 @@ void main(void) {
|
|||||||
uniform float u_myUniform;
|
uniform float u_myUniform;
|
||||||
uniform vec2 u_myUniform2;
|
uniform vec2 u_myUniform2;
|
||||||
varying vec2 v_texCoord;
|
varying vec2 v_texCoord;
|
||||||
|
varying vec2 v_quadCoord;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
|
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
@@ -226,7 +240,7 @@ 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 = parseSymbolStyle({
|
||||||
symbolType: 'circle',
|
symbolType: 'square',
|
||||||
size: [4, 8],
|
size: [4, 8],
|
||||||
color: '#336699',
|
color: '#336699',
|
||||||
rotateWithView: true
|
rotateWithView: true
|
||||||
@@ -235,7 +249,7 @@ void main(void) {
|
|||||||
uniforms: [],
|
uniforms: [],
|
||||||
attributes: [],
|
attributes: [],
|
||||||
varyings: [],
|
varyings: [],
|
||||||
colorExpression: 'vec4(0.2, 0.4, 0.6, 1.0) * vec4(1.0, 1.0, 1.0, 1.0)',
|
colorExpression: 'vec4(0.2, 0.4, 0.6, 1.0) * vec4(1.0, 1.0, 1.0, 1.0 * 1.0)',
|
||||||
sizeExpression: 'vec2(4.0, 8.0)',
|
sizeExpression: 'vec2(4.0, 8.0)',
|
||||||
offsetExpression: 'vec2(0.0, 0.0)',
|
offsetExpression: 'vec2(0.0, 0.0)',
|
||||||
texCoordExpression: 'vec4(0.0, 0.0, 1.0, 1.0)',
|
texCoordExpression: 'vec4(0.0, 0.0, 1.0, 1.0)',
|
||||||
@@ -247,7 +261,7 @@ void main(void) {
|
|||||||
|
|
||||||
it('parses a style with expressions', function() {
|
it('parses a style with expressions', function() {
|
||||||
const result = parseSymbolStyle({
|
const result = parseSymbolStyle({
|
||||||
symbolType: 'circle',
|
symbolType: 'square',
|
||||||
size: ['get', 'attr1'],
|
size: ['get', 'attr1'],
|
||||||
color: [
|
color: [
|
||||||
1.0, 0.0, 0.5, ['get', 'attr2']
|
1.0, 0.0, 0.5, ['get', 'attr2']
|
||||||
@@ -259,11 +273,15 @@ void main(void) {
|
|||||||
uniforms: [],
|
uniforms: [],
|
||||||
attributes: ['float a_attr1', 'float a_attr3', 'float a_attr2'],
|
attributes: ['float a_attr1', 'float a_attr3', 'float a_attr2'],
|
||||||
varyings: [{
|
varyings: [{
|
||||||
|
name: 'v_attr1',
|
||||||
|
type: 'float',
|
||||||
|
expression: 'a_attr1'
|
||||||
|
}, {
|
||||||
name: 'v_attr2',
|
name: 'v_attr2',
|
||||||
type: 'float',
|
type: 'float',
|
||||||
expression: 'a_attr2'
|
expression: 'a_attr2'
|
||||||
}],
|
}],
|
||||||
colorExpression: 'vec4(1.0, 0.0, 0.5, v_attr2) * vec4(1.0, 1.0, 1.0, 1.0)',
|
colorExpression: 'vec4(1.0, 0.0, 0.5, v_attr2) * vec4(1.0, 1.0, 1.0, 1.0 * 1.0)',
|
||||||
sizeExpression: 'vec2(a_attr1, a_attr1)',
|
sizeExpression: 'vec2(a_attr1, a_attr1)',
|
||||||
offsetExpression: 'vec2(3.0, a_attr3)',
|
offsetExpression: 'vec2(3.0, a_attr3)',
|
||||||
texCoordExpression: 'vec4(0.5, 0.5, 0.5, 1.0)',
|
texCoordExpression: 'vec4(0.5, 0.5, 0.5, 1.0)',
|
||||||
@@ -288,7 +306,7 @@ void main(void) {
|
|||||||
uniforms: ['sampler2D u_texture'],
|
uniforms: ['sampler2D u_texture'],
|
||||||
attributes: [],
|
attributes: [],
|
||||||
varyings: [],
|
varyings: [],
|
||||||
colorExpression: 'vec4(0.2, 0.4, 0.6, 1.0) * vec4(1.0, 1.0, 1.0, 0.5) * texture2D(u_texture, v_texCoord)',
|
colorExpression: '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)',
|
||||||
sizeExpression: 'vec2(6.0, 6.0)',
|
sizeExpression: 'vec2(6.0, 6.0)',
|
||||||
offsetExpression: 'vec2(0.0, 0.0)',
|
offsetExpression: 'vec2(0.0, 0.0)',
|
||||||
texCoordExpression: 'vec4(0.0, 0.0, 1.0, 1.0)',
|
texCoordExpression: 'vec4(0.0, 0.0, 1.0, 1.0)',
|
||||||
|
|||||||
Reference in New Issue
Block a user