Merge pull request #11471 from MichaelLangbein/WebGL-pre-and-postrender

Feature: added preRender and postRender methods to WebGLLayerRenderer…
This commit is contained in:
Olivier Guyot
2020-08-31 10:39:45 +02:00
committed by GitHub
4 changed files with 121 additions and 1 deletions

View File

@@ -17,7 +17,7 @@ class RenderEvent extends Event {
/**
* Transform from CSS pixels (relative to the top-left corner of the map viewport)
* to rendered pixels on this event's `context`.
* to rendered pixels on this event's `context`. Only available when a Canvas renderer is used, null otherwise.
* @type {import("../transform.js").Transform|undefined}
* @api
*/

View File

@@ -2,6 +2,8 @@
* @module ol/renderer/webgl/Layer
*/
import LayerRenderer from '../Layer.js';
import RenderEvent from '../../render/Event.js';
import RenderEventType from '../../render/EventType.js';
import WebGLHelper from '../../webgl/Helper.js';
/**
@@ -81,6 +83,36 @@ class WebGLLayerRenderer extends LayerRenderer {
getShaderCompileErrors() {
return this.helper.getShaderCompileErrors();
}
/**
* @param {import("../../render/EventType.js").default} type Event type.
* @param {import("../../PluggableMap.js").FrameState} frameState Frame state.
* @private
*/
dispatchRenderEvent_(type, frameState) {
const layer = this.getLayer();
if (layer.hasListener(type)) {
// RenderEvent does not get a context or an inversePixelTransform, because WebGL allows much less direct editing than Canvas2d does.
const event = new RenderEvent(type, null, frameState, null);
layer.dispatchEvent(event);
}
}
/**
* @param {import("../../PluggableMap.js").FrameState} frameState Frame state.
* @protected
*/
preRender(frameState) {
this.dispatchRenderEvent_(RenderEventType.PRERENDER, frameState);
}
/**
* @param {import("../../PluggableMap.js").FrameState} frameState Frame state.
* @protected
*/
postRender(frameState) {
this.dispatchRenderEvent_(RenderEventType.POSTRENDER, frameState);
}
}
const tmpArray_ = [];

View File

@@ -409,6 +409,8 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
* @return {HTMLElement} The rendered element.
*/
renderFrame(frameState) {
this.preRender(frameState);
const renderCount = this.indicesBuffer_.getSize();
this.helper.drawElements(0, renderCount);
this.helper.finalizeDraw(frameState);
@@ -425,6 +427,8 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
this.hitRenderTarget_.clearCachedData();
}
this.postRender(frameState);
return canvas;
}

View File

@@ -1,8 +1,10 @@
import Feature from '../../../../../src/ol/Feature.js';
import GeoJSON from '../../../../../src/ol/format/GeoJSON.js';
import Point from '../../../../../src/ol/geom/Point.js';
import VectorLayer from '../../../../../src/ol/layer/Vector.js';
import VectorSource from '../../../../../src/ol/source/Vector.js';
import ViewHint from '../../../../../src/ol/ViewHint.js';
import WebGLPointsLayer from '../../../../../src/ol/layer/WebGLPoints.js';
import WebGLPointsLayerRenderer from '../../../../../src/ol/renderer/webgl/PointsLayer.js';
import {WebGLWorkerMessageType} from '../../../../../src/ol/renderer/webgl/Layer.js';
import {
@@ -592,4 +594,86 @@ describe('ol.renderer.webgl.PointsLayer', function () {
);
});
});
describe('fires events', () => {
let layer, source, renderer, frameState;
beforeEach(function () {
source = new VectorSource({
features: new GeoJSON().readFeatures({
'type': 'FeatureCollection',
'features': [
{
'type': 'Feature',
'properties': {},
'geometry': {
'type': 'Point',
'coordinates': [13, 52],
},
},
],
}),
});
layer = new WebGLPointsLayer({
source,
style: {
symbol: {
symbolType: 'square',
},
},
});
renderer = new WebGLPointsLayerRenderer(layer, {
vertexShader: simpleVertexShader,
fragmentShader: simpleFragmentShader,
});
frameState = {
viewHints: [],
viewState: {
projection: getProjection('EPSG:4326'),
resolution: 0.010986328125,
rotation: 0,
center: [15, 52],
zoom: 7,
},
extent: [
11.1932373046875,
46.429931640625,
18.8067626953125,
57.570068359375,
],
size: [693, 1014],
layerIndex: 0,
layerStatesArray: [
{
layer: layer,
opacity: 1,
visible: true,
zIndex: 0,
},
],
};
});
it('fires prerender and postrender events', function (done) {
let prerenderNotified = false;
let postrenderNotified = false;
layer.once('prerender', (evt) => {
prerenderNotified = true;
});
layer.once('postrender', (evt) => {
postrenderNotified = true;
expect(prerenderNotified).to.be(true);
expect(postrenderNotified).to.be(true);
done();
});
renderer.prepareFrame(frameState);
renderer.renderFrame(frameState);
});
});
});