diff --git a/src/ol/webgl/ShaderBuilder.js b/src/ol/webgl/ShaderBuilder.js index afb5315669..376833e604 100644 --- a/src/ol/webgl/ShaderBuilder.js +++ b/src/ol/webgl/ShaderBuilder.js @@ -162,6 +162,12 @@ export class ShaderBuilder { */ this.texCoordExpression = 'vec4(0.0, 0.0, 1.0, 1.0)'; + /** + * @type {string} + * @private + */ + this.discardExpression = 'false'; + /** * @type {boolean} * @private @@ -257,6 +263,20 @@ export class ShaderBuilder { return this; } + /** + * Sets an expression to determine whether a fragment (pixel) should be discarded, + * i.e. not drawn at all. + * This expression can use all the uniforms, varyings and attributes available + * in the fragment shader, and should evaluate to a `bool` value (it will be + * used in an `if` statement) + * @param {string} expression Fragment discard expression + * @return {ShaderBuilder} the builder object + */ + setFragmentDiscardExpression(expression) { + this.texCoordExpression = expression; + return this; + } + /** * Sets whether the symbols should rotate with the view or stay aligned with the map. * Note: will only be used for point geometry shaders. @@ -296,6 +316,13 @@ export class ShaderBuilder { return this.texCoordExpression; } + /** + * @returns {string} Previously set fragment discard expression + */ + getFragmentDiscardExpression() { + return this.discardExpression; + } + /** * Generates a symbol vertex shader from the builder parameters, * intended to be used on point geometries. @@ -374,6 +401,7 @@ ${this.varyings.map(function(varying) { return 'varying ' + varying.type + ' ' + varying.name + ';'; }).join('\n')} void main(void) { + if (${this.discardExpression}) { discard; } gl_FragColor = ${this.colorExpression}; gl_FragColor.rgb *= gl_FragColor.a; }`; diff --git a/test/spec/ol/webgl/shaderbuilder.test.js b/test/spec/ol/webgl/shaderbuilder.test.js index 402eda8ae5..a26c2df3ef 100644 --- a/test/spec/ol/webgl/shaderbuilder.test.js +++ b/test/spec/ol/webgl/shaderbuilder.test.js @@ -166,6 +166,7 @@ varying vec2 v_quadCoord; varying float v_opacity; varying vec3 v_test; void main(void) { + if (false) { discard; } gl_FragColor = vec4(0.3137254901960784, 0.0, 1.0, v_opacity); gl_FragColor.rgb *= gl_FragColor.a; }`); @@ -178,6 +179,7 @@ void main(void) { builder.setSymbolOffsetExpression('vec2(' + formatArray([5, -7]) + ')'); builder.setColorExpression('vec4(' + formatColor([255, 255, 255, 1]) + ')'); builder.setTextureCoordinateExpression('vec4(' + formatArray([0, 0.5, 0.5, 1]) + ')'); + builder.setFragmentDiscardExpression('u_myUniform > 0.5'); expect(builder.getSymbolFragmentShader()).to.eql(`precision mediump float; uniform float u_myUniform; @@ -186,6 +188,7 @@ varying vec2 v_texCoord; varying vec2 v_quadCoord; void main(void) { + if (u_myUniform > 0.5) { discard; } gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); gl_FragColor.rgb *= gl_FragColor.a; }`);