Skip to content

[pull] main from openlayers:main #310

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
May 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/ol/layer/Heatmap.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,12 +261,12 @@ class Heatmap extends BaseVector {
if (typeof this.getBlur() === 'number') {
blurCompiled = 'a_blur';
blurRadiusUniforms['a_blur'] = () => this.getBlur();
builder.addUniform('float a_blur');
builder.addUniform('a_blur', 'float');
}
if (typeof this.getRadius() === 'number') {
radiusCompiled = 'a_radius';
blurRadiusUniforms['a_radius'] = () => this.getRadius();
builder.addUniform('float a_radius');
builder.addUniform('a_radius', 'float');
}

/** @type {import('../render/webgl/VectorStyleRenderer.js').AttributeDefinitions} */
Expand Down
56 changes: 33 additions & 23 deletions src/ol/render/webgl/ShaderBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,17 @@ const DEFAULT_STYLE = createDefaultStyle();

/**
* @typedef {Object} AttributeDescription
* @property {string} name Attribute name, as will be declared in the headers (including a_)
* @property {string} type Attribute type, either `float`, `vec2`, `vec4`...
* @property {string} varyingName Varying name, as will be declared in the fragment shader (including v_)
* @property {string} name Attribute name, as will be declared in the header of the vertex shader (including a_)
* @property {string} type Attribute GLSL type, either `float`, `vec2`, `vec4`...
* @property {string} varyingName Varying name, as will be declared in the header of both shaders (including v_)
* @property {string} varyingType Varying type, either `float`, `vec2`, `vec4`...
* @property {string} varyingExpression GLSL expression to assign to the varying in the vertex shader
* @property {string} varyingExpression GLSL expression to assign to the varying in the vertex shader (e.g. `unpackColor(a_myAttr)`)
*/

/**
* @typedef {Object} UniformDescription
* @property {string} name Uniform name, as will be declared in the header of the vertex shader (including u_)
* @property {string} type Uniform GLSL type, either `float`, `vec2`, `vec4`...
*/

/**
Expand All @@ -48,8 +54,8 @@ const DEFAULT_STYLE = createDefaultStyle();
*
* ```js
* const shader = new ShaderBuilder()
* .addVarying('v_width', 'float', 'a_width')
* .addUniform('u_time')
* .addAttribute('a_width', 'float')
* .addUniform('u_time', 'float)
* .setColorExpression('...')
* .setSymbolSizeExpression('...')
* .getSymbolFragmentShader();
Expand All @@ -63,7 +69,7 @@ export class ShaderBuilder {
constructor() {
/**
* Uniforms; these will be declared in the header (should include the type).
* @type {Array<string>}
* @type {Array<UniformDescription>}
* @private
*/
this.uniforms_ = [];
Expand Down Expand Up @@ -202,33 +208,37 @@ export class ShaderBuilder {
/**
* Adds a uniform accessible in both fragment and vertex shaders.
* The given name should include a type, such as `sampler2D u_texture`.
* @param {string} name Uniform name
* @param {string} name Uniform name, including the `u_` prefix
* @param {'float'|'vec2'|'vec3'|'vec4'|'sampler2D'} type GLSL type
* @return {ShaderBuilder} the builder object
*/
addUniform(name) {
this.uniforms_.push(name);
addUniform(name, type) {
this.uniforms_.push({
name,
type,
});
return this;
}

/**
* Adds an attribute accessible in the vertex shader, read from the geometry buffer.
* The given name should include a type, such as `vec2 a_position`.
* Attributes will also be made available under the same name in fragment shaders.
* @param {string} name Attribute name
* @param {'float'|'vec2'|'vec3'|'vec4'} type Type
* @param {string} [transform] Expression which will be assigned to the varying in the vertex shader, and
* @param {string} name Attribute name, including the `a_` prefix
* @param {'float'|'vec2'|'vec3'|'vec4'} type GLSL type
* @param {string} [varyingExpression] Expression which will be assigned to the varying in the vertex shader, and
* passed on to the fragment shader.
* @param {'float'|'vec2'|'vec3'|'vec4'} [transformedType] Type of the attribute after transformation;
* @param {'float'|'vec2'|'vec3'|'vec4'} [varyingType] Type of the attribute after transformation;
* e.g. `vec4` after unpacking color components
* @return {ShaderBuilder} the builder object
*/
addAttribute(name, type, transform, transformedType) {
addAttribute(name, type, varyingExpression, varyingType) {
this.attributes_.push({
name,
type,
varyingName: name.replace(/^a_/, 'v_'),
varyingType: transformedType ?? type,
varyingExpression: transform ?? name,
varyingType: varyingType ?? type,
varyingExpression: varyingExpression ?? name,
});
return this;
}
Expand Down Expand Up @@ -463,7 +473,7 @@ export class ShaderBuilder {
}

return `${COMMON_HEADER}
${this.uniforms_.map((uniform) => `uniform ${uniform};`).join('\n')}
${this.uniforms_.map((uniform) => `uniform ${uniform.type} ${uniform.name};`).join('\n')}
attribute vec2 a_position;
attribute float a_index;
attribute vec4 a_hitColor;
Expand Down Expand Up @@ -540,7 +550,7 @@ ${this.attributes_
}

return `${COMMON_HEADER}
${this.uniforms_.map((uniform) => `uniform ${uniform};`).join('\n')}
${this.uniforms_.map((uniform) => `uniform ${uniform.type} ${uniform.name};`).join('\n')}
varying vec2 v_texCoord;
varying vec4 v_hitColor;
varying vec2 v_centerPx;
Expand Down Expand Up @@ -584,7 +594,7 @@ ${this.attributes_
}

return `${COMMON_HEADER}
${this.uniforms_.map((uniform) => `uniform ${uniform};`).join('\n')}
${this.uniforms_.map((uniform) => `uniform ${uniform.type} ${uniform.name};`).join('\n')}
attribute vec2 a_segmentStart;
attribute vec2 a_segmentEnd;
attribute float a_measureStart;
Expand Down Expand Up @@ -704,7 +714,7 @@ ${this.attributes_
}

return `${COMMON_HEADER}
${this.uniforms_.map((uniform) => `uniform ${uniform};`).join('\n')}
${this.uniforms_.map((uniform) => `uniform ${uniform.type} ${uniform.name};`).join('\n')}
varying vec2 v_segmentStart;
varying vec2 v_segmentEnd;
varying float v_angleStart;
Expand Down Expand Up @@ -884,7 +894,7 @@ ${this.attributes_
}

return `${COMMON_HEADER}
${this.uniforms_.map((uniform) => `uniform ${uniform};`).join('\n')}
${this.uniforms_.map((uniform) => `uniform ${uniform.type} ${uniform.name};`).join('\n')}
attribute vec2 a_position;
attribute vec4 a_hitColor;

Expand Down Expand Up @@ -919,7 +929,7 @@ ${this.attributes_
}

return `${COMMON_HEADER}
${this.uniforms_.map((uniform) => `uniform ${uniform};`).join('\n')}
${this.uniforms_.map((uniform) => `uniform ${uniform.type} ${uniform.name};`).join('\n')}
varying vec4 v_hitColor;
${this.attributes_
.map(
Expand Down
9 changes: 7 additions & 2 deletions src/ol/render/webgl/compileUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export function applyContextToBuilder(builder, context) {
// we're not packing colors when they're passed as uniforms
glslType = 'vec4';
}
builder.addUniform(`${glslType} ${uniformName}`);
builder.addUniform(uniformName, glslType);
}

// for each feature attribute used in the fragment shader, define a varying that will be used to pass data
Expand Down Expand Up @@ -153,7 +153,12 @@ export function generateUniformsFromContext(context, variables) {
return value ? 1 : 0;
}
if (variable.type === ColorType) {
return asArray(value || '#eee');
const color = [...asArray(value || '#eee')];
color[0] /= 255;
color[1] /= 255;
color[2] /= 255;
color[3] ??= 1;
return color;
}
if (typeof value === 'string') {
return getStringNumberEquivalent(value);
Expand Down
6 changes: 3 additions & 3 deletions src/ol/render/webgl/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,11 @@ function parseImageProperties(style, builder, uniforms, prefix, textureId) {
uniforms[`u_texture${textureId}_size`] = () => {
return image.complete ? [image.width, image.height] : [0, 0];
};
builder.addUniform(`vec2 u_texture${textureId}_size`);
builder.addUniform(`u_texture${textureId}_size`, 'vec2');
const size = `u_texture${textureId}_size`;

uniforms[`u_texture${textureId}`] = image;
builder.addUniform(`sampler2D u_texture${textureId}`);
builder.addUniform(`u_texture${textureId}`, 'sampler2D');
return size;
}

Expand All @@ -184,7 +184,7 @@ function parseImageOffsetProperties(
let offsetExpression = expressionToGlsl(
context,
style[`${prefix}offset`],
NumberArrayType,
SizeType,
);
if (`${prefix}offset-origin` in style) {
switch (style[`${prefix}offset-origin`]) {
Expand Down
6 changes: 3 additions & 3 deletions src/ol/renderer/webgl/VectorTileLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,8 @@ class WebGLVectorTileLayerRenderer extends WebGLBaseTileLayerRenderer {
? `(${exisitingDiscard}) || (${discardFromMask})`
: discardFromMask,
);
builder.addUniform(`sampler2D ${Uniforms.TILE_MASK_TEXTURE}`);
builder.addUniform(`float ${Uniforms.TILE_ZOOM_LEVEL}`);
builder.addUniform(Uniforms.TILE_MASK_TEXTURE, 'sampler2D');
builder.addUniform(Uniforms.TILE_ZOOM_LEVEL, 'float');
}

this.styleRenderers_ = this.styles_.map((style) => {
Expand Down Expand Up @@ -234,7 +234,7 @@ class WebGLVectorTileLayerRenderer extends WebGLBaseTileLayerRenderer {
.setFillColorExpression(
`vec4(${Uniforms.TILE_ZOOM_LEVEL} / 50., 0., 0., 1.)`,
)
.addUniform(`float ${Uniforms.TILE_ZOOM_LEVEL}`);
.addUniform(Uniforms.TILE_ZOOM_LEVEL, 'float');
this.tileMaskProgram_ = this.helper.getProgram(
builder.getFillFragmentShader(),
builder.getFillVertexShader(),
Expand Down
2 changes: 1 addition & 1 deletion test/browser/spec/ol/layer/WebGLVector.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ describe('ol/layer/WebGLVector', function () {
expect(layer.styleVariables_['fillColor']).to.be('yellow');
const renderer = layer.getRenderer();
const uniforms = renderer.styleRenderers_[0].uniforms_;
expect(uniforms.u_var_fillColor()).to.eql([255, 255, 0, 1]);
expect(uniforms.u_var_fillColor()).to.eql([1, 1, 0, 1]);
});

it('can be called before the layer is rendered', function () {
Expand Down
2 changes: 1 addition & 1 deletion test/browser/spec/ol/layer/WebGLVectorTile.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ describe('ol/layer/WebGLVectorTile', function () {
expect(layer.styleVariables_['fillColor']).to.be('yellow');
const renderer = layer.getRenderer();
const uniforms = renderer.styleRenderers_[0].uniforms_;
expect(uniforms.u_var_fillColor()).to.eql([255, 255, 0, 1]);
expect(uniforms.u_var_fillColor()).to.eql([1, 1, 0, 1]);
});

it('can be called before the layer is rendered', function () {
Expand Down
10 changes: 8 additions & 2 deletions test/browser/spec/ol/render/webgl/compileUtil.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,9 @@ describe('ol/render/webgl/compileUtil', () => {

applyContextToBuilder(builder, context);

expect(builder.addUniform.calledWith('vec4 u_var_myColor')).to.be(true);
expect(builder.addUniform.calledWith('u_var_myColor', 'vec4')).to.be(
true,
);
expect(
builder.addAttribute.calledWith(
'a_prop_colorProp',
Expand Down Expand Up @@ -120,24 +122,28 @@ describe('ol/render/webgl/compileUtil', () => {
const context = {
variables: {
colorVar: {name: 'colorVar', type: ColorType},
anotherColorVar: {name: 'anotherColorVar', type: ColorType},
stringVar: {name: 'stringVar', type: StringType},
arrayVar: {name: 'arrayVar', type: NumberArrayType},
booleanVar: {name: 'booleanVar', type: BooleanType},
},
};
const styleVariables = {
colorVar: '#FFF',
anotherColorVar: [51, 102, 0, 0.4],
stringVar: 'hello world',
arrayVar: [1, 2, 3],
booleanVar: true,
};
const uniforms = generateUniformsFromContext(context, styleVariables);

expect(uniforms).to.have.property('u_var_colorVar');
expect(uniforms).to.have.property('u_var_anotherColorVar');
expect(uniforms).to.have.property('u_var_stringVar');
expect(uniforms).to.have.property('u_var_arrayVar');
expect(uniforms).to.have.property('u_var_booleanVar');
expect(uniforms.u_var_colorVar()).to.eql([255, 255, 255, 1]);
expect(uniforms.u_var_colorVar()).to.eql([1, 1, 1, 1]);
expect(uniforms.u_var_anotherColorVar()).to.eql([0.2, 0.4, 0, 0.4]);
expect(uniforms.u_var_stringVar()).to.eql(stringToGlsl('hello world'));
expect(uniforms.u_var_arrayVar()).to.eql([1, 2, 3]);
expect(uniforms.u_var_booleanVar()).to.eql(1);
Expand Down
12 changes: 6 additions & 6 deletions test/browser/spec/ol/render/webgl/shaderbuilder.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ void main(void) {
});
it('generates a symbol vertex shader (with uniforms and attributes)', () => {
const builder = new ShaderBuilder();
builder.addUniform('float u_myUniform');
builder.addUniform('u_myUniform', 'float');
builder.addAttribute('a_myAttr', 'vec2');
builder.setSymbolSizeExpression(`vec2(${numberToGlsl(6)})`);
builder.setSymbolOffsetExpression(arrayToGlsl([5, -7]));
Expand Down Expand Up @@ -325,8 +325,8 @@ void main(void) {
});
it('generates a symbol fragment shader (with uniforms)', () => {
const builder = new ShaderBuilder();
builder.addUniform('float u_myUniform');
builder.addUniform('vec2 u_myUniform2');
builder.addUniform('u_myUniform', 'float');
builder.addUniform('u_myUniform2', 'vec2');
builder.setSymbolSizeExpression(`vec2(${numberToGlsl(6)})`);
builder.setSymbolOffsetExpression(arrayToGlsl([5, -7]));
builder.setSymbolColorExpression(colorToGlsl([255, 255, 255, 1]));
Expand Down Expand Up @@ -375,7 +375,7 @@ void main(void) {
builder.addAttribute('a_opacity', 'float', numberToGlsl(0.4));
builder.addAttribute('a_test', 'vec3', arrayToGlsl([1, 2, 3]));
builder.addAttribute('a_myAttr', 'vec2');
builder.addUniform('float u_myUniform');
builder.addUniform('u_myUniform', 'float');
builder.setStrokeWidthExpression(numberToGlsl(4));
builder.setStrokeColorExpression(colorToGlsl([80, 0, 255, 1]));
builder.setStrokeCapExpression(stringToGlsl('butt'));
Expand Down Expand Up @@ -679,7 +679,7 @@ void main(void) {
builder.addAttribute('a_opacity', 'float', numberToGlsl(0.4));
builder.addAttribute('a_test', 'vec3', arrayToGlsl([1, 2, 3]));
builder.addAttribute('a_myAttr', 'vec2');
builder.addUniform('float u_myUniform');
builder.addUniform('u_myUniform', 'float');
builder.setFillColorExpression(colorToGlsl([80, 0, 255, 1]));
builder.setFragmentDiscardExpression('u_myUniform > 0.5');

Expand Down Expand Up @@ -717,7 +717,7 @@ void main(void) {
builder.addAttribute('a_opacity', 'float', numberToGlsl(0.4));
builder.addAttribute('a_test', 'vec3', arrayToGlsl([1, 2, 3]));
builder.addAttribute('a_myAttr', 'vec2');
builder.addUniform('float u_myUniform');
builder.addUniform('u_myUniform', 'float');
builder.setFillColorExpression(colorToGlsl([80, 0, 255, 1]));
builder.setFragmentDiscardExpression('u_myUniform > 0.5');

Expand Down
Loading
Loading