Merge pull request #9537 from jahow/webgl-geojson-refactoring
WebGL / Points renderer refactoring
This commit is contained in:
162
src/ol/renderer/webgl/Layer.js
Normal file
162
src/ol/renderer/webgl/Layer.js
Normal file
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
* @module ol/renderer/webgl/Layer
|
||||
*/
|
||||
import LayerRenderer from '../Layer.js';
|
||||
import WebGLHelper from '../../webgl/Helper';
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {Object} PostProcessesOptions
|
||||
* @property {number} [scaleRatio] Scale ratio; if < 1, the post process will render to a texture smaller than
|
||||
* the main canvas that will then be sampled up (useful for saving resource on blur steps).
|
||||
* @property {string} [vertexShader] Vertex shader source
|
||||
* @property {string} [fragmentShader] Fragment shader source
|
||||
* @property {Object.<string,import("../../webgl/Helper").UniformValue>} [uniforms] Uniform definitions for the post process step
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {Object.<string,import("../../webgl/Helper").UniformValue>} [uniforms] Uniform definitions for the post process steps
|
||||
* @property {Array<PostProcessesOptions>} [postProcesses] Post-processes definitions
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Base WebGL renderer class.
|
||||
* Holds all logic related to data manipulation & some common rendering logic
|
||||
*/
|
||||
class WebGLLayerRenderer extends LayerRenderer {
|
||||
|
||||
/**
|
||||
* @param {import("../../layer/Layer.js").default} layer Layer.
|
||||
* @param {Options=} [opt_options] Options.
|
||||
*/
|
||||
constructor(layer, opt_options) {
|
||||
super(layer);
|
||||
|
||||
const options = opt_options || {};
|
||||
|
||||
this.helper_ = new WebGLHelper({
|
||||
postProcesses: options.postProcesses,
|
||||
uniforms: options.uniforms
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
disposeInternal() {
|
||||
super.disposeInternal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Will return the last shader compilation errors. If no error happened, will return null;
|
||||
* @return {string|null} Errors, or null if last compilation was successful
|
||||
* @api
|
||||
*/
|
||||
getShaderCompileErrors() {
|
||||
return this.helper_.getShaderCompileErrors();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pushes vertices and indices to the given buffers using the geometry coordinates and the following properties
|
||||
* from the feature:
|
||||
* - `color`
|
||||
* - `opacity`
|
||||
* - `size` (for points)
|
||||
* - `u0`, `v0`, `u1`, `v1` (for points)
|
||||
* - `rotateWithView` (for points)
|
||||
* - `width` (for lines)
|
||||
* Custom attributes can be designated using the `opt_attributes` argument, otherwise other properties on the
|
||||
* feature will be ignored.
|
||||
* @param {import("../../webgl/Buffer").default} vertexBuffer WebGL buffer in which new vertices will be pushed.
|
||||
* @param {import("../../webgl/Buffer").default} indexBuffer WebGL buffer in which new indices will be pushed.
|
||||
* @param {import("../../format/GeoJSON").GeoJSONFeature} geojsonFeature Feature in geojson format, coordinates
|
||||
* expressed in EPSG:4326.
|
||||
* @param {Array<string>} [opt_attributes] Custom attributes. An array of properties which will be read from the
|
||||
* feature and pushed in the buffer in the given order. Note: attributes can only be numerical! Any other type or
|
||||
* NaN will result in `0` being pushed in the buffer.
|
||||
*/
|
||||
export function pushFeatureToBuffer(vertexBuffer, indexBuffer, geojsonFeature, opt_attributes) {
|
||||
if (!geojsonFeature.geometry) {
|
||||
return;
|
||||
}
|
||||
switch (geojsonFeature.geometry.type) {
|
||||
case 'Point':
|
||||
pushPointFeatureToBuffer_(vertexBuffer, indexBuffer, geojsonFeature, opt_attributes);
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const tmpArray_ = [];
|
||||
|
||||
/**
|
||||
* Pushes a quad (two triangles) based on a point geometry
|
||||
* @param {import("../../webgl/Buffer").default} vertexBuffer WebGL buffer
|
||||
* @param {import("../../webgl/Buffer").default} indexBuffer WebGL buffer
|
||||
* @param {import("../../format/GeoJSON").GeoJSONFeature} geojsonFeature Feature
|
||||
* @param {Array<string>} [opt_attributes] Custom attributes
|
||||
* @private
|
||||
*/
|
||||
function pushPointFeatureToBuffer_(vertexBuffer, indexBuffer, geojsonFeature, opt_attributes) {
|
||||
const stride = 12 + (opt_attributes !== undefined ? opt_attributes.length : 0);
|
||||
|
||||
const x = geojsonFeature.geometry.coordinates[0];
|
||||
const y = geojsonFeature.geometry.coordinates[1];
|
||||
const u0 = geojsonFeature.properties.u0;
|
||||
const v0 = geojsonFeature.properties.v0;
|
||||
const u1 = geojsonFeature.properties.u1;
|
||||
const v1 = geojsonFeature.properties.v1;
|
||||
const size = geojsonFeature.properties.size;
|
||||
const opacity = geojsonFeature.properties.opacity;
|
||||
const rotateWithView = geojsonFeature.properties.rotateWithView;
|
||||
const color = geojsonFeature.properties.color;
|
||||
const red = color[0];
|
||||
const green = color[1];
|
||||
const blue = color[2];
|
||||
const alpha = color[3];
|
||||
const baseIndex = vertexBuffer.getArray().length / stride;
|
||||
|
||||
// read custom numerical attributes on the feature
|
||||
const customAttributeValues = tmpArray_;
|
||||
customAttributeValues.length = opt_attributes ? opt_attributes.length : 0;
|
||||
for (let i = 0; i < customAttributeValues.length; i++) {
|
||||
customAttributeValues[i] = parseFloat(geojsonFeature.properties[opt_attributes[i]]) || 0;
|
||||
}
|
||||
|
||||
// push vertices for each of the four quad corners (first standard then custom attributes)
|
||||
vertexBuffer.getArray().push(x, y, -size / 2, -size / 2, u0, v0, opacity, rotateWithView, red, green, blue, alpha);
|
||||
Array.prototype.push.apply(vertexBuffer.getArray(), customAttributeValues);
|
||||
|
||||
vertexBuffer.getArray().push(x, y, +size / 2, -size / 2, u1, v0, opacity, rotateWithView, red, green, blue, alpha);
|
||||
Array.prototype.push.apply(vertexBuffer.getArray(), customAttributeValues);
|
||||
|
||||
vertexBuffer.getArray().push(x, y, +size / 2, +size / 2, u1, v1, opacity, rotateWithView, red, green, blue, alpha);
|
||||
Array.prototype.push.apply(vertexBuffer.getArray(), customAttributeValues);
|
||||
|
||||
vertexBuffer.getArray().push(x, y, -size / 2, +size / 2, u0, v1, opacity, rotateWithView, red, green, blue, alpha);
|
||||
Array.prototype.push.apply(vertexBuffer.getArray(), customAttributeValues);
|
||||
|
||||
indexBuffer.getArray().push(
|
||||
baseIndex, baseIndex + 1, baseIndex + 3,
|
||||
baseIndex + 1, baseIndex + 2, baseIndex + 3
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a texture of 1x1 pixel, white
|
||||
* @private
|
||||
* @return {ImageData} Image data.
|
||||
*/
|
||||
export function getBlankTexture() {
|
||||
const canvas = document.createElement('canvas');
|
||||
const image = canvas.getContext('2d').createImageData(1, 1);
|
||||
image.data[0] = image.data[1] = image.data[2] = image.data[3] = 255;
|
||||
return image;
|
||||
}
|
||||
|
||||
export default WebGLLayerRenderer;
|
||||
@@ -1,11 +1,21 @@
|
||||
/**
|
||||
* @module ol/renderer/webgl/PointsLayer
|
||||
*/
|
||||
import LayerRenderer from '../Layer';
|
||||
import WebGLArrayBuffer from '../../webgl/Buffer';
|
||||
import {DYNAMIC_DRAW, ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER, FLOAT} from '../../webgl';
|
||||
import WebGLHelper, {DefaultAttrib} from '../../webgl/Helper';
|
||||
import {DefaultAttrib, DefaultUniform} from '../../webgl/Helper';
|
||||
import GeometryType from '../../geom/GeometryType';
|
||||
import WebGLLayerRenderer, {getBlankTexture, pushFeatureToBuffer} from './Layer';
|
||||
import GeoJSON from '../../format/GeoJSON';
|
||||
import {getUid} from '../../util';
|
||||
import ViewHint from '../../ViewHint';
|
||||
import {createEmpty, equals} from '../../extent';
|
||||
import {
|
||||
create as createTransform,
|
||||
makeInverse as makeInverseTransform,
|
||||
multiply as multiplyTransform,
|
||||
apply as applyTransform
|
||||
} from '../../transform';
|
||||
|
||||
const VERTEX_SHADER = `
|
||||
precision mediump float;
|
||||
@@ -55,15 +65,6 @@ const FRAGMENT_SHADER = `
|
||||
gl_FragColor.rgb *= gl_FragColor.a;
|
||||
}`;
|
||||
|
||||
/**
|
||||
* @typedef {Object} PostProcessesOptions
|
||||
* @property {number} [scaleRatio] Scale ratio; if < 1, the post process will render to a texture smaller than
|
||||
* the main canvas that will then be sampled up (useful for saving resource on blur steps).
|
||||
* @property {string} [vertexShader] Vertex shader source
|
||||
* @property {string} [fragmentShader] Fragment shader source
|
||||
* @property {Object.<string,import("../../webgl/Helper").UniformValue>} [uniforms] Uniform definitions for the post process step
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {function(import("../../Feature").default):number} [sizeCallback] Will be called on every feature in the
|
||||
@@ -91,7 +92,7 @@ const FRAGMENT_SHADER = `
|
||||
* @property {string} [fragmentShader] Fragment shader source
|
||||
* @property {Object.<string,import("../../webgl/Helper").UniformValue>} [uniforms] Uniform definitions for the post process steps
|
||||
* Please note that `u_texture` is reserved for the main texture slot.
|
||||
* @property {Array<PostProcessesOptions>} [postProcesses] Post-processes definitions
|
||||
* @property {Array<import("./Layer").PostProcessesOptions>} [postProcesses] Post-processes definitions
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -186,22 +187,23 @@ const FRAGMENT_SHADER = `
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class WebGLPointsLayerRenderer extends LayerRenderer {
|
||||
class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
|
||||
|
||||
/**
|
||||
* @param {import("../../layer/Vector.js").default} vectorLayer Vector layer.
|
||||
* @param {Options=} [opt_options] Options.
|
||||
*/
|
||||
constructor(vectorLayer, opt_options) {
|
||||
super(vectorLayer);
|
||||
|
||||
const options = opt_options || {};
|
||||
|
||||
const uniforms = options.uniforms || {};
|
||||
uniforms.u_texture = options.texture || this.getDefaultTexture();
|
||||
this.helper_ = new WebGLHelper({
|
||||
postProcesses: options.postProcesses,
|
||||
uniforms: uniforms
|
||||
uniforms.u_texture = options.texture || getBlankTexture();
|
||||
const projectionMatrixTransform = createTransform();
|
||||
uniforms[DefaultUniform.PROJECTION_MATRIX] = projectionMatrixTransform;
|
||||
|
||||
super(vectorLayer, {
|
||||
uniforms: uniforms,
|
||||
postProcesses: options.postProcesses
|
||||
});
|
||||
|
||||
this.sourceRevision_ = -1;
|
||||
@@ -238,6 +240,38 @@ class WebGLPointsLayerRenderer extends LayerRenderer {
|
||||
this.rotateWithViewCallback_ = options.rotateWithViewCallback || function() {
|
||||
return false;
|
||||
};
|
||||
|
||||
this.geojsonFormat_ = new GeoJSON();
|
||||
|
||||
/**
|
||||
* @type {Object<string, import("../../format/GeoJSON").GeoJSONFeature>}
|
||||
* @private
|
||||
*/
|
||||
this.geojsonFeatureCache_ = {};
|
||||
|
||||
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();
|
||||
|
||||
/**
|
||||
* @type {import("../../transform.js").Transform}
|
||||
* @private
|
||||
*/
|
||||
this.invertRenderTransform_ = createTransform();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -269,58 +303,35 @@ class WebGLPointsLayerRenderer extends LayerRenderer {
|
||||
prepareFrame(frameState) {
|
||||
const vectorLayer = /** @type {import("../../layer/Vector.js").default} */ (this.getLayer());
|
||||
const vectorSource = vectorLayer.getSource();
|
||||
const viewState = frameState.viewState;
|
||||
|
||||
// TODO: get this from somewhere...
|
||||
const stride = 12;
|
||||
|
||||
this.helper_.prepareDraw(frameState);
|
||||
|
||||
if (this.sourceRevision_ < vectorSource.getRevision()) {
|
||||
// the source has changed: clear the feature cache & reload features
|
||||
const sourceChanged = this.sourceRevision_ < vectorSource.getRevision();
|
||||
if (sourceChanged) {
|
||||
this.sourceRevision_ = vectorSource.getRevision();
|
||||
this.verticesBuffer_.getArray().length = 0;
|
||||
this.indicesBuffer_.getArray().length = 0;
|
||||
this.geojsonFeatureCache_ = {};
|
||||
|
||||
const viewState = frameState.viewState;
|
||||
const projection = viewState.projection;
|
||||
const resolution = viewState.resolution;
|
||||
|
||||
// loop on features to fill the buffer
|
||||
vectorSource.loadFeatures([-Infinity, -Infinity, Infinity, Infinity], resolution, projection);
|
||||
vectorSource.forEachFeature((feature) => {
|
||||
if (!feature.getGeometry() || feature.getGeometry().getType() !== GeometryType.POINT) {
|
||||
return;
|
||||
}
|
||||
const x = this.coordCallback_(feature, 0);
|
||||
const y = this.coordCallback_(feature, 1);
|
||||
const u0 = this.texCoordCallback_(feature, 0);
|
||||
const v0 = this.texCoordCallback_(feature, 1);
|
||||
const u1 = this.texCoordCallback_(feature, 2);
|
||||
const v1 = this.texCoordCallback_(feature, 3);
|
||||
const size = this.sizeCallback_(feature);
|
||||
const opacity = this.opacityCallback_(feature);
|
||||
const rotateWithView = this.rotateWithViewCallback_(feature) ? 1 : 0;
|
||||
const color = this.colorCallback_(feature, this.colorArray_);
|
||||
const red = color[0];
|
||||
const green = color[1];
|
||||
const blue = color[2];
|
||||
const alpha = color[3];
|
||||
const baseIndex = this.verticesBuffer_.getArray().length / stride;
|
||||
|
||||
this.verticesBuffer_.getArray().push(
|
||||
x, y, -size / 2, -size / 2, u0, v0, opacity, rotateWithView, red, green, blue, alpha,
|
||||
x, y, +size / 2, -size / 2, u1, v0, opacity, rotateWithView, red, green, blue, alpha,
|
||||
x, y, +size / 2, +size / 2, u1, v1, opacity, rotateWithView, red, green, blue, alpha,
|
||||
x, y, -size / 2, +size / 2, u0, v1, opacity, rotateWithView, red, green, blue, alpha
|
||||
);
|
||||
this.indicesBuffer_.getArray().push(
|
||||
baseIndex, baseIndex + 1, baseIndex + 3,
|
||||
baseIndex + 1, baseIndex + 2, baseIndex + 3
|
||||
);
|
||||
});
|
||||
|
||||
this.helper_.flushBufferData(ARRAY_BUFFER, this.verticesBuffer_);
|
||||
this.helper_.flushBufferData(ELEMENT_ARRAY_BUFFER, this.indicesBuffer_);
|
||||
}
|
||||
|
||||
const viewNotMoving = !frameState.viewHints[ViewHint.ANIMATING] && !frameState.viewHints[ViewHint.INTERACTING];
|
||||
const extentChanged = !equals(this.previousExtent_, frameState.extent);
|
||||
if ((sourceChanged || extentChanged) && viewNotMoving) {
|
||||
this.rebuildBuffers_(frameState);
|
||||
this.previousExtent_ = frameState.extent.slice();
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// write new data
|
||||
this.helper_.bindBuffer(ARRAY_BUFFER, this.verticesBuffer_);
|
||||
this.helper_.bindBuffer(ELEMENT_ARRAY_BUFFER, this.indicesBuffer_);
|
||||
@@ -337,24 +348,54 @@ class WebGLPointsLayerRenderer extends LayerRenderer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Will return the last shader compilation errors. If no error happened, will return null;
|
||||
* @return {string|null} Errors, or null if last compilation was successful
|
||||
* @api
|
||||
*/
|
||||
getShaderCompileErrors() {
|
||||
return this.helper_.getShaderCompileErrors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a texture of 1x1 pixel, white
|
||||
* Rebuild internal webgl buffers based on current view extent; costly, should not be called too much
|
||||
* @param {import("../../PluggableMap").FrameState} frameState Frame state.
|
||||
* @private
|
||||
* @return {ImageData} Image data.
|
||||
*/
|
||||
getDefaultTexture() {
|
||||
const canvas = document.createElement('canvas');
|
||||
const image = canvas.getContext('2d').createImageData(1, 1);
|
||||
image.data[0] = image.data[1] = image.data[2] = image.data[3] = 255;
|
||||
return image;
|
||||
rebuildBuffers_(frameState) {
|
||||
const vectorLayer = /** @type {import("../../layer/Vector.js").default} */ (this.getLayer());
|
||||
const vectorSource = vectorLayer.getSource();
|
||||
|
||||
this.verticesBuffer_.getArray().length = 0;
|
||||
this.indicesBuffer_.getArray().length = 0;
|
||||
|
||||
// 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();
|
||||
let feature;
|
||||
for (let i = 0; i < features.length; i++) {
|
||||
feature = features[i];
|
||||
if (!feature.getGeometry() || feature.getGeometry().getType() !== GeometryType.POINT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let geojsonFeature = this.geojsonFeatureCache_[getUid(feature)];
|
||||
if (!geojsonFeature) {
|
||||
geojsonFeature = this.geojsonFormat_.writeFeatureObject(feature);
|
||||
this.geojsonFeatureCache_[getUid(feature)] = geojsonFeature;
|
||||
}
|
||||
|
||||
geojsonFeature.geometry.coordinates[0] = this.coordCallback_(feature, 0);
|
||||
geojsonFeature.geometry.coordinates[1] = this.coordCallback_(feature, 1);
|
||||
applyTransform(this.renderTransform_, geojsonFeature.geometry.coordinates);
|
||||
geojsonFeature.properties = geojsonFeature.properties || {};
|
||||
geojsonFeature.properties.color = this.colorCallback_(feature, this.colorArray_);
|
||||
geojsonFeature.properties.u0 = this.texCoordCallback_(feature, 0);
|
||||
geojsonFeature.properties.v0 = this.texCoordCallback_(feature, 1);
|
||||
geojsonFeature.properties.u1 = this.texCoordCallback_(feature, 2);
|
||||
geojsonFeature.properties.v1 = this.texCoordCallback_(feature, 3);
|
||||
geojsonFeature.properties.size = this.sizeCallback_(feature);
|
||||
geojsonFeature.properties.opacity = this.opacityCallback_(feature);
|
||||
geojsonFeature.properties.rotateWithView = this.rotateWithViewCallback_(feature) ? 1 : 0;
|
||||
|
||||
pushFeatureToBuffer(this.verticesBuffer_, this.indicesBuffer_, geojsonFeature);
|
||||
}
|
||||
|
||||
this.helper_.flushBufferData(ARRAY_BUFFER, this.verticesBuffer_);
|
||||
this.helper_.flushBufferData(ELEMENT_ARRAY_BUFFER, this.indicesBuffer_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ export const DefaultAttrib = {
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef {number|Array<number>|HTMLCanvasElement|HTMLImageElement|ImageData} UniformLiteralValue
|
||||
* @typedef {number|Array<number>|HTMLCanvasElement|HTMLImageElement|ImageData|import("../transform").Transform} UniformLiteralValue
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -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));
|
||||
}
|
||||
@@ -565,7 +550,9 @@ class WebGLHelper extends Disposable {
|
||||
// fill texture slots by increasing index
|
||||
gl.uniform1i(this.getUniformLocation(uniform.name), textureSlot++);
|
||||
|
||||
} else if (Array.isArray(value)) {
|
||||
} else if (Array.isArray(value) && value.length === 6) {
|
||||
this.setUniformMatrixValue(uniform.name, fromTransform(this.tmpMat4_, value));
|
||||
} else if (Array.isArray(value) && value.length <= 4) {
|
||||
switch (value.length) {
|
||||
case 2:
|
||||
gl.uniform2f(this.getUniformLocation(uniform.name), value[0], value[1]);
|
||||
@@ -689,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
|
||||
|
||||
Reference in New Issue
Block a user