Webgl points / use the helper ton compute the projection transform

The `WebGLHelper` class now provides a `makeProjectionTransform` method
that updates a transform to match the projection for a given frame state.

This also means that the WebGLHelper does not set the projection matrix
uniform anymore, this is the responsibility of the renderer as
the rendered coordinates will not be in world space from now on.
This commit is contained in:
Olivier Guyot
2019-05-14 18:59:24 +02:00
parent fb455891ce
commit 5d2b7fe4bb
3 changed files with 70 additions and 44 deletions
+14 -28
View File
@@ -12,9 +12,7 @@ import ViewHint from '../../ViewHint';
import {createEmpty, equals} from '../../extent'; import {createEmpty, equals} from '../../extent';
import { import {
create as createTransform, create as createTransform,
reset as resetTransform, rotate as rotateTransform, reset as resetTransform,
scale as scaleTransform,
translate as translateTransform,
makeInverse as makeInverseTransform, makeInverse as makeInverseTransform,
multiply as multiplyTransform, multiply as multiplyTransform,
apply as applyTransform apply as applyTransform
@@ -269,6 +267,12 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
* @private * @private
*/ */
this.renderTransform_ = createTransform(); 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(); this.previousExtent_ = frameState.extent.slice();
} }
// regenerate the transform matrix // apply the current projection transform with the invert of the one used to fill buffers
const size = frameState.size; this.helper_.makeProjectionTransform(frameState, this.currentTransform_);
const rotation = frameState.viewState.rotation; multiplyTransform(this.currentTransform_, this.invertRenderTransform_);
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);
this.helper_.prepareDraw(frameState); this.helper_.prepareDraw(frameState);
@@ -365,16 +358,9 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
this.verticesBuffer_.getArray().length = 0; this.verticesBuffer_.getArray().length = 0;
this.indicesBuffer_.getArray().length = 0; this.indicesBuffer_.getArray().length = 0;
// regenerate the transform matrix // saves the projection transform for the current frame state
const size = frameState.size; this.helper_.makeProjectionTransform(frameState, this.renderTransform_);
const rotation = frameState.viewState.rotation; makeInverseTransform(this.invertRenderTransform_, this.renderTransform_);
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]);
// loop on features to fill the buffer // loop on features to fill the buffer
const features = vectorSource.getFeatures(); const features = vectorSource.getFeatures();
@@ -382,7 +368,7 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
for (let i = 0; i < features.length; i++) { for (let i = 0; i < features.length; i++) {
feature = features[i]; feature = features[i];
if (!feature.getGeometry() || feature.getGeometry().getType() !== GeometryType.POINT) { if (!feature.getGeometry() || feature.getGeometry().getType() !== GeometryType.POINT) {
return; continue;
} }
let geojsonFeature = this.geojsonFeatureCache_[getUid(feature)]; let geojsonFeature = this.geojsonFeatureCache_[getUid(feature)];
+22 -15
View File
@@ -273,12 +273,6 @@ class WebGLHelper extends Disposable {
listen(this.canvas_, ContextEventType.RESTORED, listen(this.canvas_, ContextEventType.RESTORED,
this.handleWebGLContextRestored, this); this.handleWebGLContextRestored, this);
/**
* @private
* @type {import("../transform.js").Transform}
*/
this.projectionMatrix_ = createTransform();
/** /**
* @private * @private
* @type {import("../transform.js").Transform} * @type {import("../transform.js").Transform}
@@ -514,14 +508,6 @@ class WebGLHelper extends Disposable {
applyFrameState(frameState) { applyFrameState(frameState) {
const size = frameState.size; const size = frameState.size;
const rotation = frameState.viewState.rotation; 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_); const offsetScaleMatrix = resetTransform(this.offsetScaleMatrix_);
scaleTransform(offsetScaleMatrix, 2 / size[0], 2 / size[1]); scaleTransform(offsetScaleMatrix, 2 / size[0], 2 / size[1]);
@@ -531,7 +517,6 @@ class WebGLHelper extends Disposable {
rotateTransform(offsetRotateMatrix, -rotation); 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_SCALE_MATRIX, fromTransform(this.tmpMat4_, offsetScaleMatrix));
this.setUniformMatrixValue(DefaultUniform.OFFSET_ROTATION_MATRIX, fromTransform(this.tmpMat4_, offsetRotateMatrix)); this.setUniformMatrixValue(DefaultUniform.OFFSET_ROTATION_MATRIX, fromTransform(this.tmpMat4_, offsetRotateMatrix));
} }
@@ -691,6 +676,28 @@ class WebGLHelper extends Disposable {
return this.attribLocations_[name]; 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 * Give a value for a standard float uniform
* @param {string} uniform Uniform name * @param {string} uniform Uniform name
+34 -1
View File
@@ -1,5 +1,10 @@
import WebGLHelper from '../../../../src/ol/webgl/Helper'; 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 = ` 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);
});
});
}); });
}); });