Files
openlayers/src/ol/renderer/webgl-new/PointsLayer.js
2018-11-16 14:01:21 +01:00

163 lines
5.2 KiB
JavaScript

/**
* @module ol/renderer/webgl-new/PointsLayer
*/
import LayerRenderer from '../Layer';
import WebGLBuffer from '../../webgl/Buffer';
import {DYNAMIC_DRAW, ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER, FLOAT} from '../../webgl';
import WebGLHelper, {DefaultAttrib, DefaultUniform} from '../../webgl/Helper';
import WebGLVertex from "../../webgl/Vertex";
import WebGLFragment from "../../webgl/Fragment";
import GeometryType from "../../geom/GeometryType";
const VERTEX_SHADER = `
precision mediump float;
attribute vec2 a_position;
attribute vec2 a_texCoord;
attribute float a_rotateWithView;
attribute vec2 a_offsets;
uniform mat4 u_projectionMatrix;
uniform mat4 u_offsetScaleMatrix;
uniform mat4 u_offsetRotateMatrix;
varying vec2 v_texCoord;
void main(void) {
mat4 offsetMatrix = u_offsetScaleMatrix;
if (a_rotateWithView == 1.0) {
offsetMatrix = u_offsetScaleMatrix * u_offsetRotateMatrix;
}
vec4 offsets = offsetMatrix * vec4(a_offsets, 0.0, 0.0);
gl_Position = u_projectionMatrix * vec4(a_position, 0.0, 1.0) + offsets;
v_texCoord = a_texCoord;
}`;
const FRAGMENT_SHADER = `
precision mediump float;
uniform float u_opacity;
varying vec2 v_texCoord;
void main(void) {
gl_FragColor.rgb = vec3(1.0, 1.0, 1.0);
float alpha = u_opacity;
if (alpha == 0.0) {
discard;
}
gl_FragColor.a = alpha;
}`;
/**
* @classdesc
* Webgl vector renderer optimized for points.
* All features will be rendered as points.
* @api
*/
class WebGLPointsLayerRenderer extends LayerRenderer {
/**
* @param {import("../../layer/Vector.js").default} vectorLayer Vector layer.
*/
constructor(vectorLayer, opt_options) {
super(vectorLayer);
const options = opt_options || {};
this.context_ = new WebGLHelper({
postProcessingShader: options.postProcessingShader
});
this.sourceRevision_ = -1;
this.verticesBuffer_ = new WebGLBuffer([], DYNAMIC_DRAW);
this.indicesBuffer_ = new WebGLBuffer([], DYNAMIC_DRAW);
const vertexShader = new WebGLVertex(options.vertexShader || VERTEX_SHADER);
const fragmentShader = new WebGLFragment(options.fragmentShader || FRAGMENT_SHADER);
this.program_ = this.context_.getProgram(fragmentShader, vertexShader);
this.context_.useProgram(this.program_);
this.sizeCallback_ = options.sizeCallback || function(feature) {
return 1;
};
this.coordCallback_ = options.coordCallback || function(feature, index) {
const geom = /** @type {import("../../geom/Point").default} */ (feature.getGeometry());
return geom.getCoordinates()[index];
}
}
/**
* @inheritDoc
*/
disposeInternal() {
super.disposeInternal();
}
/**
* @inheritDoc
*/
renderFrame(frameState, layerState) {
this.context_.applyFrameState(frameState);
this.context_.setUniformFloatValue(DefaultUniform.OPACITY, layerState.opacity);
this.context_.drawElements(0, this.indicesBuffer_.getArray().length);
this.context_.finalizeDraw();
return this.context_.getCanvas();
}
/**
* @inheritDoc
*/
prepareFrame(frameState) {
const vectorLayer = /** @type {import("../../layer/Vector.js").default} */ (this.getLayer());
const vectorSource = /** @type {import("../../source/Vector.js").default} */ (vectorLayer.getSource());
this.context_.prepareDraw(frameState.size, frameState.pixelRatio);
if (this.sourceRevision_ < vectorSource.getRevision()) {
this.sourceRevision_ = vectorSource.getRevision();
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 geom = /** @type {import("../../geom/Point").default} */ (feature.getGeometry());
const x = this.coordCallback_(feature, 0);
const y = this.coordCallback_(feature, 1);
const size = this.sizeCallback_(feature);
let stride = 6;
let baseIndex = this.verticesBuffer_.getArray().length / stride;
this.verticesBuffer_.getArray().push(
x, y, -size / 2, -size / 2, 0, 0,
x, y, +size / 2, -size / 2, 1, 0,
x, y, +size / 2, +size / 2, 1, 1,
x, y, -size / 2, +size / 2, 0, 1,
);
this.indicesBuffer_.getArray().push(
baseIndex, baseIndex + 1, baseIndex + 3,
baseIndex + 1, baseIndex + 2, baseIndex + 3
);
});
}
// write new data
this.context_.bindBuffer(ARRAY_BUFFER, this.verticesBuffer_);
this.context_.bindBuffer(ELEMENT_ARRAY_BUFFER, this.indicesBuffer_);
let bytesPerFloat = Float32Array.BYTES_PER_ELEMENT;
this.context_.enableAttributeArray(DefaultAttrib.POSITION, 2, FLOAT, bytesPerFloat * 6, 0);
this.context_.enableAttributeArray(DefaultAttrib.OFFSETS, 2, FLOAT, bytesPerFloat * 6, bytesPerFloat * 2);
this.context_.enableAttributeArray(DefaultAttrib.TEX_COORD, 2, FLOAT, bytesPerFloat * 6, bytesPerFloat * 4);
return true;
}
}
export default WebGLPointsLayerRenderer;