diff --git a/src/ol/renderer/webgl/PointsLayer.js b/src/ol/renderer/webgl/PointsLayer.js index e76b936a8a..293e84f67d 100644 --- a/src/ol/renderer/webgl/PointsLayer.js +++ b/src/ol/renderer/webgl/PointsLayer.js @@ -12,9 +12,7 @@ import ViewHint from '../../ViewHint'; import {createEmpty, equals} from '../../extent'; import { create as createTransform, - reset as resetTransform, rotate as rotateTransform, - scale as scaleTransform, - translate as translateTransform, + reset as resetTransform, makeInverse as makeInverseTransform, multiply as multiplyTransform, apply as applyTransform @@ -269,6 +267,12 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer { * @private */ this.renderTransform_ = createTransform(); + + /** + * @type {import("../../transform.js").Transform} + * @private + */ + this.invertRenderTransform_ = createTransform(); } /** @@ -321,20 +325,9 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer { this.previousExtent_ = frameState.extent.slice(); } - // regenerate the transform matrix - const size = frameState.size; - const rotation = frameState.viewState.rotation; - const resolution = frameState.viewState.resolution; - const center = frameState.viewState.center; - - resetTransform(this.currentTransform_); - scaleTransform(this.currentTransform_, 2 / (resolution * size[0]), 2 / (resolution * size[1])); - rotateTransform(this.currentTransform_, -rotation); - translateTransform(this.currentTransform_, -center[0], -center[1]); - - // the current transform - const inverseCurrentTransform = makeInverseTransform(createTransform(), this.renderTransform_); - this.currentTransform_ = multiplyTransform(this.currentTransform_, inverseCurrentTransform); + // apply the current projection transform with the invert of the one used to fill buffers + this.helper_.makeProjectionTransform(frameState, this.currentTransform_); + multiplyTransform(this.currentTransform_, this.invertRenderTransform_); this.helper_.prepareDraw(frameState); @@ -365,16 +358,9 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer { this.verticesBuffer_.getArray().length = 0; this.indicesBuffer_.getArray().length = 0; - // regenerate the transform matrix - const size = frameState.size; - const rotation = frameState.viewState.rotation; - const resolution = frameState.viewState.resolution; - const center = frameState.viewState.center; - - resetTransform(this.renderTransform_); - scaleTransform(this.renderTransform_, 2 / (resolution * size[0]), 2 / (resolution * size[1])); - rotateTransform(this.renderTransform_, -rotation); - translateTransform(this.renderTransform_, -center[0], -center[1]); + // saves the projection transform for the current frame state + this.helper_.makeProjectionTransform(frameState, this.renderTransform_); + makeInverseTransform(this.invertRenderTransform_, this.renderTransform_); // loop on features to fill the buffer const features = vectorSource.getFeatures(); @@ -382,7 +368,7 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer { for (let i = 0; i < features.length; i++) { feature = features[i]; if (!feature.getGeometry() || feature.getGeometry().getType() !== GeometryType.POINT) { - return; + continue; } let geojsonFeature = this.geojsonFeatureCache_[getUid(feature)]; diff --git a/src/ol/webgl/Helper.js b/src/ol/webgl/Helper.js index 822c744337..b5ec037408 100644 --- a/src/ol/webgl/Helper.js +++ b/src/ol/webgl/Helper.js @@ -273,12 +273,6 @@ class WebGLHelper extends Disposable { listen(this.canvas_, ContextEventType.RESTORED, this.handleWebGLContextRestored, this); - /** - * @private - * @type {import("../transform.js").Transform} - */ - this.projectionMatrix_ = createTransform(); - /** * @private * @type {import("../transform.js").Transform} @@ -514,14 +508,6 @@ class WebGLHelper extends Disposable { applyFrameState(frameState) { const size = frameState.size; const rotation = frameState.viewState.rotation; - const resolution = frameState.viewState.resolution; - const center = frameState.viewState.center; - - // set the "uniform" values (coordinates 0,0 are the center of the view) - const projectionMatrix = resetTransform(this.projectionMatrix_); - scaleTransform(projectionMatrix, 2 / (resolution * size[0]), 2 / (resolution * size[1])); - rotateTransform(projectionMatrix, -rotation); - translateTransform(projectionMatrix, -center[0], -center[1]); const offsetScaleMatrix = resetTransform(this.offsetScaleMatrix_); scaleTransform(offsetScaleMatrix, 2 / size[0], 2 / size[1]); @@ -531,7 +517,6 @@ class WebGLHelper extends Disposable { rotateTransform(offsetRotateMatrix, -rotation); } - this.setUniformMatrixValue(DefaultUniform.PROJECTION_MATRIX, fromTransform(this.tmpMat4_, projectionMatrix)); this.setUniformMatrixValue(DefaultUniform.OFFSET_SCALE_MATRIX, fromTransform(this.tmpMat4_, offsetScaleMatrix)); this.setUniformMatrixValue(DefaultUniform.OFFSET_ROTATION_MATRIX, fromTransform(this.tmpMat4_, offsetRotateMatrix)); } @@ -691,6 +676,28 @@ class WebGLHelper extends Disposable { return this.attribLocations_[name]; } + /** + * Modifies the given transform to apply the rotation/translation/scaling of the given frame state. + * The resulting transform can be used to convert world space coordinates to view coordinates. + * @param {import("../PluggableMap.js").FrameState} frameState Frame state. + * @param {import("../transform").Transform} transform Transform to update. + * @return {import("../transform").Transform} The updated transform object. + * @api + */ + makeProjectionTransform(frameState, transform) { + const size = frameState.size; + const rotation = frameState.viewState.rotation; + const resolution = frameState.viewState.resolution; + const center = frameState.viewState.center; + + resetTransform(transform); + scaleTransform(transform, 2 / (resolution * size[0]), 2 / (resolution * size[1])); + rotateTransform(transform, -rotation); + translateTransform(transform, -center[0], -center[1]); + + return transform; + } + /** * Give a value for a standard float uniform * @param {string} uniform Uniform name diff --git a/test/spec/ol/webgl/helper.test.js b/test/spec/ol/webgl/helper.test.js index 11d7469bb1..7fad2ccda4 100644 --- a/test/spec/ol/webgl/helper.test.js +++ b/test/spec/ol/webgl/helper.test.js @@ -1,5 +1,10 @@ import WebGLHelper from '../../../../src/ol/webgl/Helper'; -import {create as createTransform} from '../../../../src/ol/transform'; +import { + create as createTransform, + multiply, + rotate as rotateTransform, + scale as scaleTransform, translate as translateTransform +} from '../../../../src/ol/transform'; const VERTEX_SHADER = ` @@ -185,5 +190,33 @@ describe('ol.webgl.WebGLHelper', function() { }); }); + describe('#makeProjectionTransform', function() { + let h; + let frameState; + beforeEach(function() { + h = new WebGLHelper(); + + frameState = { + size: [100, 150], + viewState: { + rotation: 0.4, + resolution: 2, + center: [10, 20] + } + } + }); + + it('gives out the correct transform', function() { + const scaleX = 2 / frameState.size[0] / frameState.viewState.resolution; + const scaleY = 2 / frameState.size[1] / frameState.viewState.resolution; + const given = createTransform(); + const expected = createTransform(); + scaleTransform(expected, scaleX, scaleY); + rotateTransform(expected, -frameState.viewState.rotation); + translateTransform(expected, -frameState.viewState.center[0], -frameState.viewState.center[1]); + expect(h.makeProjectionTransform(frameState, given)).to.eql(expected); + }); + }); + }); });