Skip to content

Commit

Permalink
WebGL / Use style filter when generating buffers
Browse files Browse the repository at this point in the history
  • Loading branch information
jahow committed Dec 8, 2023
1 parent 630002d commit 3bef70a
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 4 deletions.
50 changes: 47 additions & 3 deletions src/ol/render/webgl/VectorStyleRenderer.js
Expand Up @@ -4,6 +4,16 @@
import WebGLArrayBuffer from '../../webgl/Buffer.js';
import {ARRAY_BUFFER, DYNAMIC_DRAW, ELEMENT_ARRAY_BUFFER} from '../../webgl.js';
import {AttributeType} from '../../webgl/Helper.js';
import {
BooleanType,
computeGeometryType,
newParsingContext,
} from '../../expr/expression.js';
import {
UNKNOWN_VALUE,
buildExpression,
newEvaluationContext,
} from '../../expr/cpu.js';
import {WebGLWorkerMessageType} from './constants.js';
import {colorEncodeId} from './utils.js';
import {
Expand Down Expand Up @@ -104,11 +114,13 @@ class VectorStyleRenderer {
* @param {VectorStyle} styleOrShaders Literal style or custom shaders
* @param {import('../../webgl/Helper.js').default} helper Helper
* @param {boolean} enableHitDetection Whether to enable the hit detection (needs compatible shader)
* @param {import("../../expr/expression.js").ExpressionValue} [filter] Optional filter expression
*/
constructor(styleOrShaders, helper, enableHitDetection) {
constructor(styleOrShaders, helper, enableHitDetection, filter) {
this.helper_ = helper;

this.hitDetectionEnabled_ = enableHitDetection;

let shaders = /** @type {StyleShaders} */ (styleOrShaders);
const isShaders = 'builder' in styleOrShaders;
if (!isShaders) {
Expand Down Expand Up @@ -166,6 +178,31 @@ class VectorStyleRenderer {
);
}

/**
* @type {function(import('../../Feature.js').FeatureLike): boolean}
* @private
*/
this.featureFilter_ = null;
if (filter) {
const parsingContext = newParsingContext();
const compiled = buildExpression(filter, BooleanType, parsingContext);
this.featureFilter_ = (feature) => {
const evalContext = newEvaluationContext();
evalContext.properties = feature.getPropertiesInternal();
if (parsingContext.featureId) {
const id = feature.getId();
if (id !== undefined) {
evalContext.featureId = id;
} else {
evalContext.featureId = null;
}
}
evalContext.geometryType = computeGeometryType(feature.getGeometry());
const result = /** @type {boolean} */ (compiled(evalContext));
return result === UNKNOWN_VALUE || result;
};
}

const hitDetectionAttributes = this.hitDetectionEnabled_
? {
hitColor: {
Expand Down Expand Up @@ -261,11 +298,18 @@ class VectorStyleRenderer {
/**
* @param {import('./MixedGeometryBatch.js').default} geometryBatch Geometry batch
* @param {import("../../transform.js").Transform} transform Transform to apply to coordinates
* @return {Promise<WebGLBuffers>} A promise resolving to WebGL buffers
* @return {Promise<WebGLBuffers|null>} A promise resolving to WebGL buffers; returns null if buffers are empty
*/
async generateBuffers(geometryBatch, transform) {
let filteredBatch = geometryBatch;
if (this.featureFilter_) {
filteredBatch = filteredBatch.filter(this.featureFilter_);
if (filteredBatch.isEmpty()) {
return null;
}
}
const renderInstructions = this.generateRenderInstructions_(
geometryBatch,
filteredBatch,
transform
);
const [polygonBuffers, lineStringBuffers, pointBuffers] = await Promise.all(
Expand Down
6 changes: 5 additions & 1 deletion src/ol/renderer/webgl/VectorTileLayer.js
Expand Up @@ -198,7 +198,8 @@ class WebGLVectorTileLayerRenderer extends WebGLBaseTileLayerRenderer {
return new VectorStyleRenderer(
shaders,
this.helper,
this.hitDetectionEnabled_
this.hitDetectionEnabled_,
'filter' in style ? style.filter : null
);
});
}
Expand Down Expand Up @@ -339,6 +340,9 @@ class WebGLVectorTileLayerRenderer extends WebGLBaseTileLayerRenderer {
for (let i = 0, ii = this.styleRenderers_.length; i < ii; i++) {
const renderer = this.styleRenderers_[i];
const buffers = tileRepresentation.buffers[i];
if (!buffers) {
continue;
}
renderer.render(buffers, frameState, () => {
this.applyUniforms_(
alpha,
Expand Down
2 changes: 2 additions & 0 deletions src/ol/webgl/styleparser.js
Expand Up @@ -921,6 +921,8 @@ export function parseLiteralStyle(style) {
parseStrokeProperties(style, builder, uniforms, vertContext, fragContext);
parseFillProperties(style, builder, uniforms, vertContext, fragContext);

// note that the style filter may have already been applied earlier when building the rendering instructions
// this is still needed in case a filter cannot be evaluated statically beforehand (e.g. depending on time)
if (style.filter) {
const parsedFilter = expressionToGlsl(
fragContext,
Expand Down

0 comments on commit 3bef70a

Please sign in to comment.