Webgl shader builder / expanded functionality
Now takes in a custom object with attributes, uniforms etc. The WebGLPointsLayer uses this to handle image icons.
This commit is contained in:
@@ -1,4 +1,9 @@
|
||||
import {getSymbolVertexShader, formatNumber, getSymbolFragmentShader} from '../../../../src/ol/webgl/ShaderBuilder.js';
|
||||
import {
|
||||
getSymbolVertexShader,
|
||||
formatNumber,
|
||||
getSymbolFragmentShader,
|
||||
formatColor, formatArray
|
||||
} from '../../../../src/ol/webgl/ShaderBuilder.js';
|
||||
|
||||
describe('ol.webgl.ShaderBuilder', function() {
|
||||
|
||||
@@ -12,147 +17,180 @@ describe('ol.webgl.ShaderBuilder', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('formatArray', function() {
|
||||
it('outputs numbers with dot separators', function() {
|
||||
expect(formatArray([1, 0, 3.45, 0.8888])).to.eql('1.0, 0.0, 3.45, 0.8888');
|
||||
});
|
||||
});
|
||||
|
||||
describe('formatColor', function() {
|
||||
it('normalizes color and outputs numbers with dot separators', function() {
|
||||
expect(formatColor([100, 0, 255, 1])).to.eql('0.39215686274509803, 0.0, 1.0, 1.0');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getSymbolVertexShader', function() {
|
||||
it('generates a symbol vertex shader without using additional attributes', function() {
|
||||
expect(getSymbolVertexShader(
|
||||
{
|
||||
rotateWithView: false,
|
||||
color: '#5000ff',
|
||||
opacity: 0.4,
|
||||
offset: [5, -7],
|
||||
size: 6,
|
||||
textureCoord: [0, 0.5, 0.5, 1]
|
||||
})).to.eql(`precision mediump float;
|
||||
it('generates a symbol vertex shader (with varying)', function() {
|
||||
const parameters = {
|
||||
varyings: [{
|
||||
name: 'v_opacity',
|
||||
type: 'float',
|
||||
expression: formatNumber(0.4)
|
||||
}, {
|
||||
name: 'v_test',
|
||||
type: 'vec3',
|
||||
expression: 'vec3(' + formatArray([1, 2, 3]) + ')'
|
||||
}],
|
||||
sizeExpression: 'vec2(' + formatNumber(6) + ')',
|
||||
offsetExpression: 'vec2(' + formatArray([5, -7]) + ')',
|
||||
colorExpression: 'vec4(' + formatColor([80, 0, 255, 1]) + ')',
|
||||
texCoordExpression: 'vec4(' + formatArray([0, 0.5, 0.5, 1]) + ')',
|
||||
rotateWithView: false
|
||||
};
|
||||
|
||||
expect(getSymbolVertexShader(parameters)).to.eql(`precision mediump float;
|
||||
uniform mat4 u_projectionMatrix;
|
||||
uniform mat4 u_offsetScaleMatrix;
|
||||
uniform mat4 u_offsetRotateMatrix;
|
||||
|
||||
attribute vec2 a_position;
|
||||
attribute float a_index;
|
||||
|
||||
varying vec2 v_texCoord;
|
||||
varying float v_opacity;
|
||||
varying vec4 v_color;
|
||||
varying vec3 v_test;
|
||||
void main(void) {
|
||||
mat4 offsetMatrix = u_offsetScaleMatrix;
|
||||
vec2 size = vec2(6.0);
|
||||
vec2 offset = vec2(5.0, -7.0);
|
||||
float offsetX = a_index == 0.0 || a_index == 3.0 ? offset.x - size.x / 2.0 : offset.x + size.x / 2.0;
|
||||
float offsetY = a_index == 0.0 || a_index == 1.0 ? offset.y - size.y / 2.0 : offset.y + size.y / 2.0;
|
||||
vec4 offsets = offsetMatrix * vec4(offsetX, offsetY, 0.0, 0.0);
|
||||
gl_Position = u_projectionMatrix * vec4(a_position, 0.0, 1.0) + offsets;
|
||||
vec4 texCoord = vec4(0.0, 0.5, 0.5, 1.0);
|
||||
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;
|
||||
v_texCoord = vec2(u, v);
|
||||
v_opacity = 0.4;
|
||||
v_test = vec3(1.0, 2.0, 3.0);
|
||||
}`);
|
||||
});
|
||||
it('generates a symbol vertex shader (with uniforms and attributes)', function() {
|
||||
const parameters = {
|
||||
uniforms: ['float u_myUniform'],
|
||||
attributes: ['vec2 a_myAttr'],
|
||||
sizeExpression: 'vec2(' + formatNumber(6) + ')',
|
||||
offsetExpression: 'vec2(' + formatArray([5, -7]) + ')',
|
||||
colorExpression: 'vec4(' + formatColor([80, 0, 255, 1]) + ')',
|
||||
texCoordExpression: 'vec4(' + formatArray([0, 0.5, 0.5, 1]) + ')'
|
||||
};
|
||||
|
||||
expect(getSymbolVertexShader(parameters)).to.eql(`precision mediump float;
|
||||
uniform mat4 u_projectionMatrix;
|
||||
uniform mat4 u_offsetScaleMatrix;
|
||||
uniform mat4 u_offsetRotateMatrix;
|
||||
uniform float u_myUniform;
|
||||
attribute vec2 a_position;
|
||||
attribute float a_index;
|
||||
attribute vec2 a_myAttr;
|
||||
varying vec2 v_texCoord;
|
||||
|
||||
void main(void) {
|
||||
mat4 offsetMatrix = u_offsetScaleMatrix;
|
||||
float offsetX = a_index == 0.0 || a_index == 3.0 ? 2.0 : 8.0;
|
||||
float offsetY = a_index == 0.0 || a_index == 1.0 ? -10.0 : -4.0;
|
||||
vec2 size = vec2(6.0);
|
||||
vec2 offset = vec2(5.0, -7.0);
|
||||
float offsetX = a_index == 0.0 || a_index == 3.0 ? offset.x - size.x / 2.0 : offset.x + size.x / 2.0;
|
||||
float offsetY = a_index == 0.0 || a_index == 1.0 ? offset.y - size.y / 2.0 : offset.y + size.y / 2.0;
|
||||
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 ? 0.0 : 0.5;
|
||||
float v = a_index == 0.0 || a_index == 1.0 ? 0.5 : 1.0;
|
||||
vec4 texCoord = vec4(0.0, 0.5, 0.5, 1.0);
|
||||
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;
|
||||
v_texCoord = vec2(u, v);
|
||||
v_opacity = 0.4;
|
||||
v_color = vec4(0.3137254901960784, 0.0, 1.0, 1.0);
|
||||
}`);
|
||||
});
|
||||
it('correctly handles size as an array', function() {
|
||||
expect(getSymbolVertexShader(
|
||||
{
|
||||
rotateWithView: false,
|
||||
color: '#5000ff',
|
||||
opacity: 0.4,
|
||||
offset: [5, -7],
|
||||
size: [10, 12],
|
||||
textureCoord: [0, 0.5, 0.5, 1]
|
||||
})).to.eql(`precision mediump float;
|
||||
uniform mat4 u_projectionMatrix;
|
||||
uniform mat4 u_offsetScaleMatrix;
|
||||
uniform mat4 u_offsetRotateMatrix;
|
||||
attribute vec2 a_position;
|
||||
attribute float a_index;
|
||||
varying vec2 v_texCoord;
|
||||
varying float v_opacity;
|
||||
varying vec4 v_color;
|
||||
|
||||
void main(void) {
|
||||
mat4 offsetMatrix = u_offsetScaleMatrix;
|
||||
float offsetX = a_index == 0.0 || a_index == 3.0 ? 0.0 : 10.0;
|
||||
float offsetY = a_index == 0.0 || a_index == 1.0 ? -13.0 : -1.0;
|
||||
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 ? 0.0 : 0.5;
|
||||
float v = a_index == 0.0 || a_index == 1.0 ? 0.5 : 1.0;
|
||||
v_texCoord = vec2(u, v);
|
||||
v_opacity = 0.4;
|
||||
v_color = vec4(0.3137254901960784, 0.0, 1.0, 1.0);
|
||||
}`);
|
||||
});
|
||||
it('correctly handles rotate with view', function() {
|
||||
expect(getSymbolVertexShader(
|
||||
{
|
||||
rotateWithView: true,
|
||||
color: '#5000ff',
|
||||
opacity: 0.4,
|
||||
size: 6,
|
||||
textureCoord: [0, 0.5, 0.5, 1]
|
||||
})).to.eql(`precision mediump float;
|
||||
it('generates a symbol vertex shader (with rotateWithView)', function() {
|
||||
const parameters = {
|
||||
sizeExpression: 'vec2(' + formatNumber(6) + ')',
|
||||
offsetExpression: 'vec2(' + formatArray([5, -7]) + ')',
|
||||
colorExpression: 'vec4(' + formatColor([80, 0, 255, 1]) + ')',
|
||||
texCoordExpression: 'vec4(' + formatArray([0, 0.5, 0.5, 1]) + ')',
|
||||
rotateWithView: true
|
||||
};
|
||||
|
||||
expect(getSymbolVertexShader(parameters)).to.eql(`precision mediump float;
|
||||
uniform mat4 u_projectionMatrix;
|
||||
uniform mat4 u_offsetScaleMatrix;
|
||||
uniform mat4 u_offsetRotateMatrix;
|
||||
|
||||
attribute vec2 a_position;
|
||||
attribute float a_index;
|
||||
|
||||
varying vec2 v_texCoord;
|
||||
varying float v_opacity;
|
||||
varying vec4 v_color;
|
||||
|
||||
void main(void) {
|
||||
mat4 offsetMatrix = u_offsetScaleMatrix * u_offsetRotateMatrix;
|
||||
float offsetX = a_index == 0.0 || a_index == 3.0 ? -3.0 : 3.0;
|
||||
float offsetY = a_index == 0.0 || a_index == 1.0 ? -3.0 : 3.0;
|
||||
vec2 size = vec2(6.0);
|
||||
vec2 offset = vec2(5.0, -7.0);
|
||||
float offsetX = a_index == 0.0 || a_index == 3.0 ? offset.x - size.x / 2.0 : offset.x + size.x / 2.0;
|
||||
float offsetY = a_index == 0.0 || a_index == 1.0 ? offset.y - size.y / 2.0 : offset.y + size.y / 2.0;
|
||||
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 ? 0.0 : 0.5;
|
||||
float v = a_index == 0.0 || a_index == 1.0 ? 0.5 : 1.0;
|
||||
vec4 texCoord = vec4(0.0, 0.5, 0.5, 1.0);
|
||||
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;
|
||||
v_texCoord = vec2(u, v);
|
||||
v_opacity = 0.4;
|
||||
v_color = vec4(0.3137254901960784, 0.0, 1.0, 1.0);
|
||||
}`);
|
||||
});
|
||||
it('correctly handles missing optional parameters', function() {
|
||||
expect(getSymbolVertexShader(
|
||||
{
|
||||
rotateWithView: false,
|
||||
size: 5
|
||||
})).to.eql(`precision mediump float;
|
||||
uniform mat4 u_projectionMatrix;
|
||||
uniform mat4 u_offsetScaleMatrix;
|
||||
uniform mat4 u_offsetRotateMatrix;
|
||||
attribute vec2 a_position;
|
||||
attribute float a_index;
|
||||
varying vec2 v_texCoord;
|
||||
varying float v_opacity;
|
||||
varying vec4 v_color;
|
||||
|
||||
void main(void) {
|
||||
mat4 offsetMatrix = u_offsetScaleMatrix;
|
||||
float offsetX = a_index == 0.0 || a_index == 3.0 ? -2.5 : 2.5;
|
||||
float offsetY = a_index == 0.0 || a_index == 1.0 ? -2.5 : 2.5;
|
||||
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 ? 0.0 : 1.0;
|
||||
float v = a_index == 0.0 || a_index == 1.0 ? 0.0 : 1.0;
|
||||
v_texCoord = vec2(u, v);
|
||||
v_opacity = 1.0;
|
||||
v_color = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
}`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getSymbolFragmentShader', function() {
|
||||
it('generates a fixed shader', function() {
|
||||
expect(getSymbolFragmentShader()).to.eql(`precision mediump float;
|
||||
uniform sampler2D u_texture;
|
||||
it('generates a symbol fragment shader (with varying)', function() {
|
||||
const parameters = {
|
||||
varyings: [{
|
||||
name: 'v_opacity',
|
||||
type: 'float',
|
||||
expression: formatNumber(0.4)
|
||||
}, {
|
||||
name: 'v_test',
|
||||
type: 'vec3',
|
||||
expression: 'vec3(' + formatArray([1, 2, 3]) + ')'
|
||||
}],
|
||||
sizeExpression: 'vec2(' + formatNumber(6) + ')',
|
||||
offsetExpression: 'vec2(' + formatArray([5, -7]) + ')',
|
||||
colorExpression: 'vec4(' + formatColor([80, 0, 255]) + ', v_opacity)',
|
||||
texCoordExpression: 'vec4(' + formatArray([0, 0.5, 0.5, 1]) + ')',
|
||||
rotateWithView: false
|
||||
};
|
||||
|
||||
expect(getSymbolFragmentShader(parameters)).to.eql(`precision mediump float;
|
||||
|
||||
varying vec2 v_texCoord;
|
||||
varying float v_opacity;
|
||||
varying vec4 v_color;
|
||||
varying vec3 v_test;
|
||||
void main(void) {
|
||||
gl_FragColor = vec4(0.3137254901960784, 0.0, 1.0, v_opacity);
|
||||
gl_FragColor.rgb *= gl_FragColor.a;
|
||||
}`);
|
||||
});
|
||||
it('generates a symbol fragment shader (with uniforms)', function() {
|
||||
const parameters = {
|
||||
uniforms: ['float u_myUniform', 'vec2 u_myUniform2'],
|
||||
sizeExpression: 'vec2(' + formatNumber(6) + ')',
|
||||
offsetExpression: 'vec2(' + formatArray([5, -7]) + ')',
|
||||
colorExpression: 'vec4(' + formatColor([255, 255, 255, 1]) + ')',
|
||||
texCoordExpression: 'vec4(' + formatArray([0, 0.5, 0.5, 1]) + ')'
|
||||
};
|
||||
|
||||
expect(getSymbolFragmentShader(parameters)).to.eql(`precision mediump float;
|
||||
uniform float u_myUniform;
|
||||
uniform vec2 u_myUniform2;
|
||||
varying vec2 v_texCoord;
|
||||
|
||||
void main(void) {
|
||||
if (v_opacity == 0.0) {
|
||||
discard;
|
||||
}
|
||||
vec4 textureColor = texture2D(u_texture, v_texCoord);
|
||||
gl_FragColor = v_color * textureColor;
|
||||
gl_FragColor.a *= v_opacity;
|
||||
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
gl_FragColor.rgb *= gl_FragColor.a;
|
||||
}`);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user