Webgl points / make coordinates in view space to avoid precision glitches
Fixes #9479
This commit is contained in:
@@ -3,13 +3,22 @@
|
|||||||
*/
|
*/
|
||||||
import WebGLArrayBuffer from '../../webgl/Buffer';
|
import WebGLArrayBuffer from '../../webgl/Buffer';
|
||||||
import {DYNAMIC_DRAW, ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER, FLOAT} from '../../webgl';
|
import {DYNAMIC_DRAW, ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER, FLOAT} from '../../webgl';
|
||||||
import {DefaultAttrib} from '../../webgl/Helper';
|
import {DefaultAttrib, DefaultUniform} from '../../webgl/Helper';
|
||||||
import GeometryType from '../../geom/GeometryType';
|
import GeometryType from '../../geom/GeometryType';
|
||||||
import WebGLLayerRenderer, {getBlankTexture, pushFeatureInBuffer} from './Layer';
|
import WebGLLayerRenderer, {getBlankTexture, pushFeatureInBuffer} from './Layer';
|
||||||
import GeoJSON from '../../format/GeoJSON';
|
import GeoJSON from '../../format/GeoJSON';
|
||||||
import {getUid} from '../../util';
|
import {getUid} from '../../util';
|
||||||
import ViewHint from '../../ViewHint';
|
import ViewHint from '../../ViewHint';
|
||||||
import {createEmpty, equals} from '../../extent';
|
import {createEmpty, equals} from '../../extent';
|
||||||
|
import {
|
||||||
|
create as createTransform,
|
||||||
|
reset as resetTransform, rotate as rotateTransform,
|
||||||
|
scale as scaleTransform,
|
||||||
|
translate as translateTransform,
|
||||||
|
makeInverse as makeInverseTransform,
|
||||||
|
multiply as multiplyTransform,
|
||||||
|
apply as applyTransform
|
||||||
|
} from '../../transform';
|
||||||
|
|
||||||
const VERTEX_SHADER = `
|
const VERTEX_SHADER = `
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
@@ -190,9 +199,10 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
|
|||||||
constructor(vectorLayer, opt_options) {
|
constructor(vectorLayer, opt_options) {
|
||||||
const options = opt_options || {};
|
const options = opt_options || {};
|
||||||
|
|
||||||
// assign the `texture` uniform if not specified in the options
|
|
||||||
const uniforms = options.uniforms || {};
|
const uniforms = options.uniforms || {};
|
||||||
uniforms.u_texture = options.texture || getBlankTexture();
|
uniforms.u_texture = options.texture || getBlankTexture();
|
||||||
|
const projectionMatrixTransform = createTransform();
|
||||||
|
uniforms[DefaultUniform.PROJECTION_MATRIX] = projectionMatrixTransform;
|
||||||
|
|
||||||
super(vectorLayer, {
|
super(vectorLayer, {
|
||||||
uniforms: uniforms,
|
uniforms: uniforms,
|
||||||
@@ -243,6 +253,22 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
|
|||||||
this.geojsonFeatureCache_ = {};
|
this.geojsonFeatureCache_ = {};
|
||||||
|
|
||||||
this.previousExtent_ = createEmpty();
|
this.previousExtent_ = createEmpty();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This transform is updated on every frame and is the composition of:
|
||||||
|
* - invert of the world->screen transform that was used when rebuilding buffers (see `this.renderTransform_`)
|
||||||
|
* - current world->screen transform
|
||||||
|
* @type {import("../../transform.js").Transform}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.currentTransform_ = projectionMatrixTransform;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This transform is updated when buffers are rebuilt and converts world space coordinates to screen space
|
||||||
|
* @type {import("../../transform.js").Transform}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.renderTransform_ = createTransform();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -279,8 +305,6 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
|
|||||||
// TODO: get this from somewhere...
|
// TODO: get this from somewhere...
|
||||||
const stride = 12;
|
const stride = 12;
|
||||||
|
|
||||||
this.helper_.prepareDraw(frameState);
|
|
||||||
|
|
||||||
// the source has changed: clear the feature cache & reload features
|
// the source has changed: clear the feature cache & reload features
|
||||||
if (this.sourceRevision_ < vectorSource.getRevision()) {
|
if (this.sourceRevision_ < vectorSource.getRevision()) {
|
||||||
this.sourceRevision_ = vectorSource.getRevision();
|
this.sourceRevision_ = vectorSource.getRevision();
|
||||||
@@ -297,6 +321,23 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
|
|||||||
this.previousExtent_ = frameState.extent.slice();
|
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);
|
||||||
|
|
||||||
|
this.helper_.prepareDraw(frameState);
|
||||||
|
|
||||||
// write new data
|
// write new data
|
||||||
this.helper_.bindBuffer(ARRAY_BUFFER, this.verticesBuffer_);
|
this.helper_.bindBuffer(ARRAY_BUFFER, this.verticesBuffer_);
|
||||||
this.helper_.bindBuffer(ELEMENT_ARRAY_BUFFER, this.indicesBuffer_);
|
this.helper_.bindBuffer(ELEMENT_ARRAY_BUFFER, this.indicesBuffer_);
|
||||||
@@ -324,6 +365,17 @@ 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
|
||||||
|
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]);
|
||||||
|
|
||||||
// loop on features to fill the buffer
|
// loop on features to fill the buffer
|
||||||
const features = vectorSource.getFeatures();
|
const features = vectorSource.getFeatures();
|
||||||
let feature;
|
let feature;
|
||||||
@@ -341,6 +393,7 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
|
|||||||
|
|
||||||
geojsonFeature.geometry.coordinates[0] = this.coordCallback_(feature, 0);
|
geojsonFeature.geometry.coordinates[0] = this.coordCallback_(feature, 0);
|
||||||
geojsonFeature.geometry.coordinates[1] = this.coordCallback_(feature, 1);
|
geojsonFeature.geometry.coordinates[1] = this.coordCallback_(feature, 1);
|
||||||
|
applyTransform(this.renderTransform_, geojsonFeature.geometry.coordinates);
|
||||||
geojsonFeature.properties = geojsonFeature.properties || {};
|
geojsonFeature.properties = geojsonFeature.properties || {};
|
||||||
geojsonFeature.properties.color = this.colorCallback_(feature, this.colorArray_);
|
geojsonFeature.properties.color = this.colorCallback_(feature, this.colorArray_);
|
||||||
geojsonFeature.properties.u0 = this.texCoordCallback_(feature, 0);
|
geojsonFeature.properties.u0 = this.texCoordCallback_(feature, 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user