openlayers
Version:
Build tools and sources for developing OpenLayers based mapping applications
267 lines (215 loc) • 7.14 kB
JavaScript
goog.provide('ol.renderer.webgl.Layer');
goog.require('ol');
goog.require('ol.render.Event');
goog.require('ol.render.webgl.Immediate');
goog.require('ol.renderer.Layer');
goog.require('ol.renderer.webgl.defaultmapshader');
goog.require('ol.transform');
goog.require('ol.vec.Mat4');
goog.require('ol.webgl');
goog.require('ol.webgl.Buffer');
goog.require('ol.webgl.Context');
/**
* @constructor
* @extends {ol.renderer.Layer}
* @param {ol.renderer.webgl.Map} mapRenderer Map renderer.
* @param {ol.layer.Layer} layer Layer.
*/
ol.renderer.webgl.Layer = function(mapRenderer, layer) {
ol.renderer.Layer.call(this, layer);
/**
* @protected
* @type {ol.renderer.webgl.Map}
*/
this.mapRenderer = mapRenderer;
/**
* @private
* @type {ol.webgl.Buffer}
*/
this.arrayBuffer_ = new ol.webgl.Buffer([
-1, -1, 0, 0,
1, -1, 1, 0,
-1, 1, 0, 1,
1, 1, 1, 1
]);
/**
* @protected
* @type {WebGLTexture}
*/
this.texture = null;
/**
* @protected
* @type {WebGLFramebuffer}
*/
this.framebuffer = null;
/**
* @protected
* @type {number|undefined}
*/
this.framebufferDimension = undefined;
/**
* @protected
* @type {ol.Transform}
*/
this.texCoordMatrix = ol.transform.create();
/**
* @protected
* @type {ol.Transform}
*/
this.projectionMatrix = ol.transform.create();
/**
* @type {Array.<number>}
* @private
*/
this.tmpMat4_ = ol.vec.Mat4.create();
/**
* @private
* @type {ol.renderer.webgl.defaultmapshader.Locations}
*/
this.defaultLocations_ = null;
};
ol.inherits(ol.renderer.webgl.Layer, ol.renderer.Layer);
/**
* @param {olx.FrameState} frameState Frame state.
* @param {number} framebufferDimension Framebuffer dimension.
* @protected
*/
ol.renderer.webgl.Layer.prototype.bindFramebuffer = function(frameState, framebufferDimension) {
var gl = this.mapRenderer.getGL();
if (this.framebufferDimension === undefined ||
this.framebufferDimension != framebufferDimension) {
/**
* @param {WebGLRenderingContext} gl GL.
* @param {WebGLFramebuffer} framebuffer Framebuffer.
* @param {WebGLTexture} texture Texture.
*/
var postRenderFunction = function(gl, framebuffer, texture) {
if (!gl.isContextLost()) {
gl.deleteFramebuffer(framebuffer);
gl.deleteTexture(texture);
}
}.bind(null, gl, this.framebuffer, this.texture);
frameState.postRenderFunctions.push(
/** @type {ol.PostRenderFunction} */ (postRenderFunction)
);
var texture = ol.webgl.Context.createEmptyTexture(
gl, framebufferDimension, framebufferDimension);
var framebuffer = gl.createFramebuffer();
gl.bindFramebuffer(ol.webgl.FRAMEBUFFER, framebuffer);
gl.framebufferTexture2D(ol.webgl.FRAMEBUFFER,
ol.webgl.COLOR_ATTACHMENT0, ol.webgl.TEXTURE_2D, texture, 0);
this.texture = texture;
this.framebuffer = framebuffer;
this.framebufferDimension = framebufferDimension;
} else {
gl.bindFramebuffer(ol.webgl.FRAMEBUFFER, this.framebuffer);
}
};
/**
* @param {olx.FrameState} frameState Frame state.
* @param {ol.LayerState} layerState Layer state.
* @param {ol.webgl.Context} context Context.
*/
ol.renderer.webgl.Layer.prototype.composeFrame = function(frameState, layerState, context) {
this.dispatchComposeEvent_(
ol.render.Event.Type.PRECOMPOSE, context, frameState);
context.bindBuffer(ol.webgl.ARRAY_BUFFER, this.arrayBuffer_);
var gl = context.getGL();
var fragmentShader = ol.renderer.webgl.defaultmapshader.fragment;
var vertexShader = ol.renderer.webgl.defaultmapshader.vertex;
var program = context.getProgram(fragmentShader, vertexShader);
var locations;
if (!this.defaultLocations_) {
locations =
new ol.renderer.webgl.defaultmapshader.Locations(gl, program);
this.defaultLocations_ = locations;
} else {
locations = this.defaultLocations_;
}
if (context.useProgram(program)) {
gl.enableVertexAttribArray(locations.a_position);
gl.vertexAttribPointer(
locations.a_position, 2, ol.webgl.FLOAT, false, 16, 0);
gl.enableVertexAttribArray(locations.a_texCoord);
gl.vertexAttribPointer(
locations.a_texCoord, 2, ol.webgl.FLOAT, false, 16, 8);
gl.uniform1i(locations.u_texture, 0);
}
gl.uniformMatrix4fv(locations.u_texCoordMatrix, false,
ol.vec.Mat4.fromTransform(this.tmpMat4_, this.getTexCoordMatrix()));
gl.uniformMatrix4fv(locations.u_projectionMatrix, false,
ol.vec.Mat4.fromTransform(this.tmpMat4_, this.getProjectionMatrix()));
gl.uniform1f(locations.u_opacity, layerState.opacity);
gl.bindTexture(ol.webgl.TEXTURE_2D, this.getTexture());
gl.drawArrays(ol.webgl.TRIANGLE_STRIP, 0, 4);
this.dispatchComposeEvent_(
ol.render.Event.Type.POSTCOMPOSE, context, frameState);
};
/**
* @param {ol.render.Event.Type} type Event type.
* @param {ol.webgl.Context} context WebGL context.
* @param {olx.FrameState} frameState Frame state.
* @private
*/
ol.renderer.webgl.Layer.prototype.dispatchComposeEvent_ = function(type, context, frameState) {
var layer = this.getLayer();
if (layer.hasListener(type)) {
var viewState = frameState.viewState;
var resolution = viewState.resolution;
var pixelRatio = frameState.pixelRatio;
var extent = frameState.extent;
var center = viewState.center;
var rotation = viewState.rotation;
var size = frameState.size;
var render = new ol.render.webgl.Immediate(
context, center, resolution, rotation, size, extent, pixelRatio);
var composeEvent = new ol.render.Event(
type, render, frameState, null, context);
layer.dispatchEvent(composeEvent);
}
};
/**
* @return {!ol.Transform} Matrix.
*/
ol.renderer.webgl.Layer.prototype.getTexCoordMatrix = function() {
return this.texCoordMatrix;
};
/**
* @return {WebGLTexture} Texture.
*/
ol.renderer.webgl.Layer.prototype.getTexture = function() {
return this.texture;
};
/**
* @return {!ol.Transform} Matrix.
*/
ol.renderer.webgl.Layer.prototype.getProjectionMatrix = function() {
return this.projectionMatrix;
};
/**
* Handle webglcontextlost.
*/
ol.renderer.webgl.Layer.prototype.handleWebGLContextLost = function() {
this.texture = null;
this.framebuffer = null;
this.framebufferDimension = undefined;
};
/**
* @abstract
* @param {olx.FrameState} frameState Frame state.
* @param {ol.LayerState} layerState Layer state.
* @param {ol.webgl.Context} context Context.
* @return {boolean} whether composeFrame should be called.
*/
ol.renderer.webgl.Layer.prototype.prepareFrame = function(frameState, layerState, context) {};
/**
* @abstract
* @param {ol.Pixel} pixel Pixel.
* @param {olx.FrameState} frameState FrameState.
* @param {function(this: S, ol.layer.Layer, (Uint8ClampedArray|Uint8Array)): T} callback Layer
* callback.
* @param {S} thisArg Value to use as `this` when executing `callback`.
* @return {T|undefined} Callback result.
* @template S,T,U
*/
ol.renderer.webgl.Layer.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg) {};