Avoid colliding user variables with internal names
This commit is contained in:
@@ -378,6 +378,15 @@ Operators['get'] = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the uniform name given a variable name.
|
||||||
|
* @param {string} variableName The variable name.
|
||||||
|
* @return {string} The uniform name.
|
||||||
|
*/
|
||||||
|
export function uniformNameForVariable(variableName) {
|
||||||
|
return 'u_var_' + variableName;
|
||||||
|
}
|
||||||
|
|
||||||
Operators['var'] = {
|
Operators['var'] = {
|
||||||
getReturnType: function (args) {
|
getReturnType: function (args) {
|
||||||
return ValueTypes.ANY;
|
return ValueTypes.ANY;
|
||||||
@@ -389,7 +398,7 @@ Operators['var'] = {
|
|||||||
if (context.variables.indexOf(value) === -1) {
|
if (context.variables.indexOf(value) === -1) {
|
||||||
context.variables.push(value);
|
context.variables.push(value);
|
||||||
}
|
}
|
||||||
return `u_${value}`;
|
return uniformNameForVariable(value);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
ValueTypes,
|
ValueTypes,
|
||||||
expressionToGlsl,
|
expressionToGlsl,
|
||||||
getStringNumberEquivalent,
|
getStringNumberEquivalent,
|
||||||
|
uniformNameForVariable,
|
||||||
} from '../style/expressions.js';
|
} from '../style/expressions.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -527,8 +528,9 @@ export function parseLiteralStyle(style) {
|
|||||||
|
|
||||||
// define one uniform per variable
|
// define one uniform per variable
|
||||||
fragContext.variables.forEach(function (varName) {
|
fragContext.variables.forEach(function (varName) {
|
||||||
builder.addUniform(`float u_${varName}`);
|
const uniformName = uniformNameForVariable(varName);
|
||||||
uniforms[`u_${varName}`] = function () {
|
builder.addUniform(`float ${uniformName}`);
|
||||||
|
uniforms[uniformName] = function () {
|
||||||
if (!style.variables || style.variables[varName] === undefined) {
|
if (!style.variables || style.variables[varName] === undefined) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`The following variable is missing from the style: ${varName}`
|
`The following variable is missing from the style: ${varName}`
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
isTypeUnique,
|
isTypeUnique,
|
||||||
numberToGlsl,
|
numberToGlsl,
|
||||||
stringToGlsl,
|
stringToGlsl,
|
||||||
|
uniformNameForVariable,
|
||||||
} from '../../../../src/ol/style/expressions.js';
|
} from '../../../../src/ol/style/expressions.js';
|
||||||
|
|
||||||
describe('ol.style.expressions', function () {
|
describe('ol.style.expressions', function () {
|
||||||
@@ -211,7 +212,9 @@ describe('ol.style.expressions', function () {
|
|||||||
|
|
||||||
it('correctly converts expressions to GLSL', function () {
|
it('correctly converts expressions to GLSL', function () {
|
||||||
expect(expressionToGlsl(context, ['get', 'myAttr'])).to.eql('a_myAttr');
|
expect(expressionToGlsl(context, ['get', 'myAttr'])).to.eql('a_myAttr');
|
||||||
expect(expressionToGlsl(context, ['var', 'myValue'])).to.eql('u_myValue');
|
expect(expressionToGlsl(context, ['var', 'myValue'])).to.eql(
|
||||||
|
uniformNameForVariable('myValue')
|
||||||
|
);
|
||||||
expect(expressionToGlsl(context, ['time'])).to.eql('u_time');
|
expect(expressionToGlsl(context, ['time'])).to.eql('u_time');
|
||||||
expect(expressionToGlsl(context, ['zoom'])).to.eql('u_zoom');
|
expect(expressionToGlsl(context, ['zoom'])).to.eql('u_zoom');
|
||||||
expect(expressionToGlsl(context, ['resolution'])).to.eql('u_resolution');
|
expect(expressionToGlsl(context, ['resolution'])).to.eql('u_resolution');
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
arrayToGlsl,
|
arrayToGlsl,
|
||||||
colorToGlsl,
|
colorToGlsl,
|
||||||
numberToGlsl,
|
numberToGlsl,
|
||||||
|
uniformNameForVariable,
|
||||||
} from '../../../../src/ol/style/expressions.js';
|
} from '../../../../src/ol/style/expressions.js';
|
||||||
|
|
||||||
describe('ol.webgl.ShaderBuilder', function () {
|
describe('ol.webgl.ShaderBuilder', function () {
|
||||||
@@ -477,9 +478,11 @@ void main(void) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const lowerUniformName = uniformNameForVariable('lower');
|
||||||
|
const higherUniformName = uniformNameForVariable('higher');
|
||||||
expect(result.builder.uniforms).to.eql([
|
expect(result.builder.uniforms).to.eql([
|
||||||
'float u_lower',
|
`float ${lowerUniformName}`,
|
||||||
'float u_higher',
|
`float ${higherUniformName}`,
|
||||||
]);
|
]);
|
||||||
expect(result.builder.attributes).to.eql(['float a_population']);
|
expect(result.builder.attributes).to.eql(['float a_population']);
|
||||||
expect(result.builder.varyings).to.eql([
|
expect(result.builder.varyings).to.eql([
|
||||||
@@ -493,7 +496,7 @@ void main(void) {
|
|||||||
'vec4(vec4(0.2, 0.4, 0.6, 1.0).rgb, vec4(0.2, 0.4, 0.6, 1.0).a * 0.5 * 1.0)'
|
'vec4(vec4(0.2, 0.4, 0.6, 1.0).rgb, vec4(0.2, 0.4, 0.6, 1.0).a * 0.5 * 1.0)'
|
||||||
);
|
);
|
||||||
expect(result.builder.sizeExpression).to.eql(
|
expect(result.builder.sizeExpression).to.eql(
|
||||||
'vec2(mix(4.0, 8.0, pow(clamp((a_population - u_lower) / (u_higher - u_lower), 0.0, 1.0), 1.0)))'
|
`vec2(mix(4.0, 8.0, pow(clamp((a_population - ${lowerUniformName}) / (${higherUniformName} - ${lowerUniformName}), 0.0, 1.0), 1.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(
|
expect(result.builder.texCoordExpression).to.eql(
|
||||||
@@ -502,8 +505,8 @@ void main(void) {
|
|||||||
expect(result.builder.rotateWithView).to.eql(false);
|
expect(result.builder.rotateWithView).to.eql(false);
|
||||||
expect(result.attributes.length).to.eql(1);
|
expect(result.attributes.length).to.eql(1);
|
||||||
expect(result.attributes[0].name).to.eql('population');
|
expect(result.attributes[0].name).to.eql('population');
|
||||||
expect(result.uniforms).to.have.property('u_lower');
|
expect(result.uniforms).to.have.property(lowerUniformName);
|
||||||
expect(result.uniforms).to.have.property('u_higher');
|
expect(result.uniforms).to.have.property(higherUniformName);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('parses a style with a filter', function () {
|
it('parses a style with a filter', function () {
|
||||||
@@ -541,6 +544,8 @@ void main(void) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('parses a style with a color interpolation', function () {
|
it('parses a style with a color interpolation', function () {
|
||||||
|
const varName = 'ratio';
|
||||||
|
const uniformName = uniformNameForVariable(varName);
|
||||||
const result = parseLiteralStyle({
|
const result = parseLiteralStyle({
|
||||||
symbol: {
|
symbol: {
|
||||||
symbolType: 'square',
|
symbolType: 'square',
|
||||||
@@ -548,7 +553,7 @@ void main(void) {
|
|||||||
color: [
|
color: [
|
||||||
'interpolate',
|
'interpolate',
|
||||||
['linear'],
|
['linear'],
|
||||||
['var', 'ratio'],
|
['var', varName],
|
||||||
0,
|
0,
|
||||||
[255, 255, 0],
|
[255, 255, 0],
|
||||||
1,
|
1,
|
||||||
@@ -560,7 +565,7 @@ void main(void) {
|
|||||||
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(mix(vec4(1.0, 1.0, 0.0, 1.0), vec4(1.0, 0.0, 0.0, 1.0), pow(clamp((u_ratio - 0.0) / (1.0 - 0.0), 0.0, 1.0), 1.0)).rgb, mix(vec4(1.0, 1.0, 0.0, 1.0), vec4(1.0, 0.0, 0.0, 1.0), pow(clamp((u_ratio - 0.0) / (1.0 - 0.0), 0.0, 1.0), 1.0)).a * 1.0 * 1.0)'
|
`vec4(mix(vec4(1.0, 1.0, 0.0, 1.0), vec4(1.0, 0.0, 0.0, 1.0), pow(clamp((${uniformName} - 0.0) / (1.0 - 0.0), 0.0, 1.0), 1.0)).rgb, mix(vec4(1.0, 1.0, 0.0, 1.0), vec4(1.0, 0.0, 0.0, 1.0), pow(clamp((${uniformName} - 0.0) / (1.0 - 0.0), 0.0, 1.0), 1.0)).a * 1.0 * 1.0)`
|
||||||
);
|
);
|
||||||
expect(result.builder.sizeExpression).to.eql('vec2(6.0)');
|
expect(result.builder.sizeExpression).to.eql('vec2(6.0)');
|
||||||
expect(result.builder.offsetExpression).to.eql('vec2(0.0, 0.0)');
|
expect(result.builder.offsetExpression).to.eql('vec2(0.0, 0.0)');
|
||||||
@@ -569,7 +574,7 @@ void main(void) {
|
|||||||
);
|
);
|
||||||
expect(result.builder.rotateWithView).to.eql(false);
|
expect(result.builder.rotateWithView).to.eql(false);
|
||||||
expect(result.attributes).to.eql([]);
|
expect(result.attributes).to.eql([]);
|
||||||
expect(result.uniforms).to.have.property('u_ratio');
|
expect(result.uniforms).to.have.property(uniformName);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('parses a style with a rotation expression using an attribute', function () {
|
it('parses a style with a rotation expression using an attribute', function () {
|
||||||
@@ -587,32 +592,38 @@ void main(void) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('correctly adds string variables to the string literals mapping', function () {
|
it('correctly adds string variables to the string literals mapping', function () {
|
||||||
|
const varName = 'mySize';
|
||||||
|
const uniformName = uniformNameForVariable(varName);
|
||||||
|
|
||||||
const result = parseLiteralStyle({
|
const result = parseLiteralStyle({
|
||||||
variables: {
|
variables: {
|
||||||
mySize: 'abcdef',
|
mySize: 'abcdef',
|
||||||
},
|
},
|
||||||
symbol: {
|
symbol: {
|
||||||
symbolType: 'square',
|
symbolType: 'square',
|
||||||
size: ['match', ['var', 'mySize'], 'abc', 10, 'def', 20, 30],
|
size: ['match', ['var', varName], 'abc', 10, 'def', 20, 30],
|
||||||
color: 'red',
|
color: 'red',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result.uniforms['u_mySize']()).to.be.greaterThan(0);
|
expect(result.uniforms[uniformName]()).to.be.greaterThan(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('throws when a variable is requested but not present in the style', function (done) {
|
it('throws when a variable is requested but not present in the style', function (done) {
|
||||||
|
const varName = 'mySize';
|
||||||
|
const uniformName = uniformNameForVariable(varName);
|
||||||
|
|
||||||
const result = parseLiteralStyle({
|
const result = parseLiteralStyle({
|
||||||
variables: {},
|
variables: {},
|
||||||
symbol: {
|
symbol: {
|
||||||
symbolType: 'square',
|
symbolType: 'square',
|
||||||
size: ['var', 'mySize'],
|
size: ['var', varName],
|
||||||
color: 'red',
|
color: 'red',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
result.uniforms['u_mySize']();
|
result.uniforms[uniformName]();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
@@ -620,16 +631,18 @@ void main(void) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('throws when a variable is requested but the style does not have a variables dict', function (done) {
|
it('throws when a variable is requested but the style does not have a variables dict', function (done) {
|
||||||
|
const variableName = 'mySize';
|
||||||
|
const uniformName = uniformNameForVariable(variableName);
|
||||||
const result = parseLiteralStyle({
|
const result = parseLiteralStyle({
|
||||||
symbol: {
|
symbol: {
|
||||||
symbolType: 'square',
|
symbolType: 'square',
|
||||||
size: ['var', 'mySize'],
|
size: ['var', variableName],
|
||||||
color: 'red',
|
color: 'red',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
result.uniforms['u_mySize']();
|
result.uniforms[uniformName]();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user