diff --git a/examples/icon.js b/examples/icon.js index d510cf16fa..ab9cb41deb 100644 --- a/examples/icon.js +++ b/examples/icon.js @@ -5,7 +5,7 @@ goog.require('ol.View'); goog.require('ol.geom.Point'); goog.require('ol.layer.Tile'); goog.require('ol.layer.Vector'); -goog.require('ol.source.TileJSON'); +goog.require('ol.source.OSM'); goog.require('ol.source.Vector'); goog.require('ol.style.Icon'); goog.require('ol.style.Style'); diff --git a/src/ol/render/canvas/canvasreplay.js b/src/ol/render/canvas/canvasreplay.js index 5d7b35aef6..e2ab0f38e0 100644 --- a/src/ol/render/canvas/canvasreplay.js +++ b/src/ol/render/canvas/canvasreplay.js @@ -2011,7 +2011,7 @@ ol.render.canvas.ReplayGroup.prototype.forEachGeometryAtPixel = function( /** - * @inheritDoc + * FIXME empty description for jsdoc */ ol.render.canvas.ReplayGroup.prototype.finish = function() { var zKey; diff --git a/src/ol/render/ireplay.js b/src/ol/render/ireplay.js index 3f4d7c122a..78e2faf67a 100644 --- a/src/ol/render/ireplay.js +++ b/src/ol/render/ireplay.js @@ -35,13 +35,6 @@ ol.render.IReplayGroup = function() { }; -/** - * FIXME empty description for jsdoc - */ -ol.render.IReplayGroup.prototype.finish = function() { -}; - - /** * @param {number|undefined} zIndex Z index. * @param {ol.render.ReplayType} replayType Replay type. diff --git a/src/ol/render/webgl/webglreplay.js b/src/ol/render/webgl/webglreplay.js new file mode 100644 index 0000000000..849a87e848 --- /dev/null +++ b/src/ol/render/webgl/webglreplay.js @@ -0,0 +1,367 @@ +goog.provide('ol.render.webgl.ReplayGroup'); + +goog.require('goog.array'); +goog.require('goog.asserts'); +goog.require('goog.object'); +goog.require('ol.extent'); +goog.require('ol.render.IReplayGroup'); + + + +/** + * @constructor + * @implements {ol.render.IVectorContext} + * @param {number} tolerance Tolerance. + * @protected + * @struct + */ +ol.render.webgl.Replay = function(tolerance) { + + /** + * @protected + * @type {Array.} + */ + this.coordinates = []; + + /** + * @protected + * @type {WebGLBuffer} + */ + this.buffer = null; + + /** + * @private + * @type {ol.Extent} + */ + this.extent_ = ol.extent.createEmpty(); + +}; + + +/** + * @param {Array.} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} stride Stride. + * @param {boolean} close Close. + * @protected + * @return {number} My end. + */ +ol.render.webgl.Replay.prototype.appendFlatCoordinates = + function(flatCoordinates, offset, end, stride, close) { + var myEnd = this.coordinates.length; + var i; + for (i = offset; i < end; i += stride) { + this.coordinates[myEnd++] = flatCoordinates[i]; + this.coordinates[myEnd++] = flatCoordinates[i + 1]; + } + if (close) { + this.coordinates[myEnd++] = flatCoordinates[offset]; + this.coordinates[myEnd++] = flatCoordinates[offset + 1]; + } + return myEnd; +}; + + +/** + * @param {ol.webgl.Context} context Context. + */ +ol.render.webgl.Replay.prototype.finish = goog.nullFunction; + + +/** + * @param {ol.webgl.Context} context Context. + * @param {number} attribLocation Attribute location. + * @param {WebGLUniformLocation} projectionMatrixLocation Projection + * matrix location. + * @param {number} pixelRatio Pixel ratio. + * @param {goog.vec.Mat4.Number} transform Transform. + * @param {Object} skippedFeaturesHash Ids of features to skip. + * @return {T|undefined} Callback result. + * @template T + */ +ol.render.webgl.Replay.prototype.replay = + function(context, attribLocation, projectionMatrixLocation, + pixelRatio, transform, skippedFeaturesHash) { + var gl = context.getGL(); + gl.bindBuffer(goog.webgl.ARRAY_BUFFER, this.buffer); + gl.uniformMatrix4fv(projectionMatrixLocation, false, + transform); + gl.enableVertexAttribArray(attribLocation); + gl.vertexAttribPointer(attribLocation, 2, goog.webgl.FLOAT, + false, 0, 0); + gl.drawArrays(goog.webgl.POINTS, 0, this.coordinates.length / 2); +}; + + +/** + * @inheritDoc + */ +ol.render.webgl.Replay.prototype.drawAsync = goog.abstractMethod; + + +/** + * @inheritDoc + */ +ol.render.webgl.Replay.prototype.drawCircleGeometry = goog.abstractMethod; + + +/** + * @inheritDoc + */ +ol.render.webgl.Replay.prototype.drawFeature = goog.abstractMethod; + + +/** + * @inheritDoc + */ +ol.render.webgl.Replay.prototype.drawGeometryCollectionGeometry = + goog.abstractMethod; + + +/** + * @inheritDoc + */ +ol.render.webgl.Replay.prototype.drawLineStringGeometry = goog.abstractMethod; + + +/** + * @inheritDoc + */ +ol.render.webgl.Replay.prototype.drawMultiLineStringGeometry = + goog.abstractMethod; + + +/** + * @inheritDoc + */ +ol.render.webgl.Replay.prototype.drawPointGeometry = goog.abstractMethod; + + +/** + * @inheritDoc + */ +ol.render.webgl.Replay.prototype.drawMultiPointGeometry = goog.abstractMethod; + + +/** + * @inheritDoc + */ +ol.render.webgl.Replay.prototype.drawPolygonGeometry = goog.abstractMethod; + + +/** + * @inheritDoc + */ +ol.render.webgl.Replay.prototype.drawMultiPolygonGeometry = + goog.abstractMethod; + + +/** + * @inheritDoc + */ +ol.render.webgl.Replay.prototype.drawText = goog.abstractMethod; + + +/** + * @inheritDoc + */ +ol.render.webgl.Replay.prototype.setFillStrokeStyle = goog.abstractMethod; + + +/** + * @inheritDoc + */ +ol.render.webgl.Replay.prototype.setImageStyle = goog.abstractMethod; + + +/** + * @inheritDoc + */ +ol.render.webgl.Replay.prototype.setTextStyle = goog.abstractMethod; + + + +/** + * @constructor + * @extends {ol.render.webgl.Replay} + * @param {number} tolerance Tolerance. + * @protected + * @struct + */ +ol.render.webgl.ImageReplay = function(tolerance) { + + goog.base(this, tolerance); + +}; +goog.inherits(ol.render.webgl.ImageReplay, ol.render.webgl.Replay); + + +/** + * @param {Array.} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} stride Stride. + * @private + * @return {number} My end. + */ +ol.render.webgl.ImageReplay.prototype.drawCoordinates_ = + function(flatCoordinates, offset, end, stride) { + return this.appendFlatCoordinates( + flatCoordinates, offset, end, stride, false); +}; + + +/** + * @inheritDoc + */ +ol.render.webgl.ImageReplay.prototype.drawPointGeometry = + function(pointGeometry, data) { + ol.extent.extend(this.extent_, pointGeometry.getExtent()); + var flatCoordinates = pointGeometry.getFlatCoordinates(); + var stride = pointGeometry.getStride(); + this.drawCoordinates_( + flatCoordinates, 0, flatCoordinates.length, stride); +}; + + +/** + * @inheritDoc + */ +ol.render.webgl.ImageReplay.prototype.drawMultiPointGeometry = + function(multiPointGeometry, data) { + ol.extent.extend(this.extent_, multiPointGeometry.getExtent()); + var flatCoordinates = multiPointGeometry.getFlatCoordinates(); + var stride = multiPointGeometry.getStride(); + this.drawCoordinates_( + flatCoordinates, 0, flatCoordinates.length, stride); +}; + + +/** + * @param {ol.webgl.Context} context Context. + */ +ol.render.webgl.ImageReplay.prototype.finish = function(context) { + var gl = context.getGL(); + this.buffer = gl.createBuffer(); + gl.bindBuffer(goog.webgl.ARRAY_BUFFER, this.buffer); + gl.bufferData(goog.webgl.ARRAY_BUFFER, + new Float32Array(this.coordinates), goog.webgl.STATIC_DRAW); +}; + + +/** + * @return {ol.Extent} Extent. + */ +ol.render.webgl.Replay.prototype.getExtent = function() { + return this.extent_; +}; + + +/** + * @inheritDoc + */ +ol.render.webgl.ImageReplay.prototype.setImageStyle = function(imageStyle) { +}; + + + +/** + * @constructor + * @implements {ol.render.IReplayGroup} + * @param {number} tolerance Tolerance. + * @struct + */ +ol.render.webgl.ReplayGroup = function(tolerance) { + + /** + * @private + * @type {number} + */ + this.tolerance_ = tolerance; + + /** + * @private + * @type {Object.} + */ + this.replays_ = {}; + +}; + + +/** + * @param {ol.webgl.Context} context Context. + */ +ol.render.webgl.ReplayGroup.prototype.finish = function(context) { + var replayKey; + for (replayKey in this.replays_) { + this.replays_[replayKey].finish(context); + } +}; + + +/** + * @inheritDoc + */ +ol.render.webgl.ReplayGroup.prototype.getReplay = + function(zIndex, replayType) { + var replay = this.replays_[replayType]; + if (!goog.isDef(replay)) { + var constructor = ol.render.webgl.BATCH_CONSTRUCTORS_[replayType]; + goog.asserts.assert(goog.isDef(constructor)); + replay = new constructor(this.tolerance_); + this.replays_[replayType] = replay; + } + return replay; +}; + + +/** + * @inheritDoc + */ +ol.render.webgl.ReplayGroup.prototype.isEmpty = function() { + return goog.object.isEmpty(this.replays_); +}; + + +/** + * @param {ol.webgl.Context} context Context. + * @param {number} attribLocation Attribute location. + * @param {WebGLUniformLocation} projectionMatrixLocation Projection + * matrix location. + * @param {ol.Extent} extent Extent. + * @param {number} pixelRatio Pixel ratio. + * @param {goog.vec.Mat4.Number} transform Transform. + * @param {Object} skippedFeaturesHash Ids of features to skip. + * @return {T|undefined} Callback result. + * @template T + */ +ol.render.webgl.ReplayGroup.prototype.replay = function( + context, attribLocation, projectionMatrixLocation, extent, + pixelRatio, transform, skippedFeaturesHash) { + var i, ii, replay, result; + for (i = 0, ii = ol.render.REPLAY_ORDER.length; i < ii; ++i) { + replay = this.replays_[ol.render.REPLAY_ORDER[i]]; + if (goog.isDef(replay) && + ol.extent.intersects(extent, replay.getExtent())) { + result = replay.replay( + context, attribLocation, projectionMatrixLocation, + pixelRatio, transform, skippedFeaturesHash); + if (result) { + return result; + } + } + } + return undefined; +}; + + +/** + * @const + * @private + * @type {Object.} + */ +ol.render.webgl.BATCH_CONSTRUCTORS_ = { + 'Image': ol.render.webgl.ImageReplay +}; diff --git a/src/ol/renderer/canvas/canvaslayerrenderer.js b/src/ol/renderer/canvas/canvaslayerrenderer.js index 65fa90866e..f48f64eb7a 100644 --- a/src/ol/renderer/canvas/canvaslayerrenderer.js +++ b/src/ol/renderer/canvas/canvaslayerrenderer.js @@ -172,6 +172,14 @@ ol.renderer.canvas.Layer.prototype.getTransform = function(frameState) { }; +/** + * @param {olx.FrameState} frameState Frame state. + * @param {ol.layer.LayerState} layerState Layer state. + * @return {boolean} whether composeFrame should be called. + */ +ol.renderer.canvas.Layer.prototype.prepareFrame = goog.abstractMethod; + + /** * @param {ol.Size} size Size. * @return {boolean} True when the canvas with the current size does not exceed diff --git a/src/ol/renderer/dom/domlayerrenderer.js b/src/ol/renderer/dom/domlayerrenderer.js index df94a74b2e..072e32435e 100644 --- a/src/ol/renderer/dom/domlayerrenderer.js +++ b/src/ol/renderer/dom/domlayerrenderer.js @@ -46,3 +46,11 @@ ol.renderer.dom.Layer.prototype.composeFrame = goog.nullFunction; ol.renderer.dom.Layer.prototype.getTarget = function() { return this.target; }; + + +/** + * @param {olx.FrameState} frameState Frame state. + * @param {ol.layer.LayerState} layerState Layer state. + * @return {boolean} whether composeFrame should be called. + */ +ol.renderer.dom.Layer.prototype.prepareFrame = goog.abstractMethod; diff --git a/src/ol/renderer/layerrenderer.js b/src/ol/renderer/layerrenderer.js index ef9ee9029d..356561bb0f 100644 --- a/src/ol/renderer/layerrenderer.js +++ b/src/ol/renderer/layerrenderer.js @@ -6,7 +6,6 @@ goog.require('ol.ImageState'); goog.require('ol.TileRange'); goog.require('ol.TileState'); goog.require('ol.layer.Layer'); -goog.require('ol.layer.LayerState'); goog.require('ol.source.Source'); goog.require('ol.source.State'); goog.require('ol.source.Tile'); @@ -95,14 +94,6 @@ ol.renderer.Layer.prototype.handleImageChange = function(event) { }; -/** - * @param {olx.FrameState} frameState Frame state. - * @param {ol.layer.LayerState} layerState Layer state. - * @return {boolean} whether composeFrame should be called. - */ -ol.renderer.Layer.prototype.prepareFrame = goog.abstractMethod; - - /** * @protected */ diff --git a/src/ol/renderer/webgl/webglimagelayerrenderer.js b/src/ol/renderer/webgl/webglimagelayerrenderer.js index 7022b626e9..9b093e7e44 100644 --- a/src/ol/renderer/webgl/webglimagelayerrenderer.js +++ b/src/ol/renderer/webgl/webglimagelayerrenderer.js @@ -100,7 +100,7 @@ ol.renderer.webgl.ImageLayer.prototype.forEachFeatureAtPixel = * @inheritDoc */ ol.renderer.webgl.ImageLayer.prototype.prepareFrame = - function(frameState, layerState) { + function(frameState, layerState, context) { var gl = this.getWebGLMapRenderer().getGL(); diff --git a/src/ol/renderer/webgl/webgllayerrenderer.js b/src/ol/renderer/webgl/webgllayerrenderer.js index 823ffcc184..6c51fc0394 100644 --- a/src/ol/renderer/webgl/webgllayerrenderer.js +++ b/src/ol/renderer/webgl/webgllayerrenderer.js @@ -286,3 +286,12 @@ ol.renderer.webgl.Layer.prototype.handleWebGLContextLost = function() { this.framebuffer = null; this.framebufferDimension = undefined; }; + + +/** + * @param {olx.FrameState} frameState Frame state. + * @param {ol.layer.LayerState} layerState Layer state. + * @param {ol.webgl.Context} context Context. + * @return {boolean} whether composeFrame should be called. + */ +ol.renderer.webgl.Layer.prototype.prepareFrame = goog.abstractMethod; diff --git a/src/ol/renderer/webgl/webglmaprenderer.js b/src/ol/renderer/webgl/webglmaprenderer.js index 12d5982bee..f093ba274f 100644 --- a/src/ol/renderer/webgl/webglmaprenderer.js +++ b/src/ol/renderer/webgl/webglmaprenderer.js @@ -20,6 +20,7 @@ goog.require('ol.dom'); goog.require('ol.layer.Image'); goog.require('ol.layer.Layer'); goog.require('ol.layer.Tile'); +goog.require('ol.layer.Vector'); goog.require('ol.render.Event'); goog.require('ol.render.EventType'); goog.require('ol.render.webgl.Immediate'); @@ -27,6 +28,7 @@ goog.require('ol.renderer.Map'); goog.require('ol.renderer.webgl.ImageLayer'); goog.require('ol.renderer.webgl.Layer'); goog.require('ol.renderer.webgl.TileLayer'); +goog.require('ol.renderer.webgl.VectorLayer'); goog.require('ol.source.State'); goog.require('ol.structs.LRUCache'); goog.require('ol.structs.PriorityQueue'); @@ -250,6 +252,8 @@ ol.renderer.webgl.Map.prototype.createLayerRenderer = function(layer) { return new ol.renderer.webgl.ImageLayer(this, layer); } else if (ol.ENABLE_TILE && layer instanceof ol.layer.Tile) { return new ol.renderer.webgl.TileLayer(this, layer); + } else if (ol.ENABLE_VECTOR && layer instanceof ol.layer.Vector) { + return new ol.renderer.webgl.VectorLayer(this, layer); } else { goog.asserts.fail(); return null; @@ -455,7 +459,7 @@ ol.renderer.webgl.Map.prototype.renderFrame = function(frameState) { layerState.sourceState == ol.source.State.READY) { layerRenderer = this.getLayerRenderer(layerState.layer); goog.asserts.assertInstanceof(layerRenderer, ol.renderer.webgl.Layer); - if (layerRenderer.prepareFrame(frameState, layerState)) { + if (layerRenderer.prepareFrame(frameState, layerState, context)) { layerStatesToDraw.push(layerState); } } diff --git a/src/ol/renderer/webgl/webgltilelayerrenderer.js b/src/ol/renderer/webgl/webgltilelayerrenderer.js index b9cfb26b24..426f0fbc4e 100644 --- a/src/ol/renderer/webgl/webgltilelayerrenderer.js +++ b/src/ol/renderer/webgl/webgltilelayerrenderer.js @@ -107,11 +107,10 @@ ol.renderer.webgl.TileLayer.prototype.handleWebGLContextLost = function() { * @inheritDoc */ ol.renderer.webgl.TileLayer.prototype.prepareFrame = - function(frameState, layerState) { + function(frameState, layerState, context) { var mapRenderer = this.getWebGLMapRenderer(); - var context = mapRenderer.getContext(); - var gl = mapRenderer.getGL(); + var gl = context.getGL(); var viewState = frameState.viewState; var projection = viewState.projection; diff --git a/src/ol/renderer/webgl/webglvectorlayer.glsl b/src/ol/renderer/webgl/webglvectorlayer.glsl new file mode 100644 index 0000000000..cc8aaf7dc2 --- /dev/null +++ b/src/ol/renderer/webgl/webglvectorlayer.glsl @@ -0,0 +1,23 @@ +//! NAMESPACE=ol.renderer.webgl.vectorlayer.shader +//! CLASS=ol.renderer.webgl.vectorlayer.shader. + + +//! COMMON + + +//! VERTEX +attribute vec2 a_position; + +uniform mat4 u_projectionMatrix; + +void main(void) { + gl_PointSize = 10.0; + gl_Position = u_projectionMatrix * vec4(a_position, 0., 1.); +} + + +//! FRAGMENT + +void main(void) { + gl_FragColor = vec4(1.0, 1.0, 0.0, 0.7); +} diff --git a/src/ol/renderer/webgl/webglvectorlayerrenderer.js b/src/ol/renderer/webgl/webglvectorlayerrenderer.js new file mode 100644 index 0000000000..ef285cfde0 --- /dev/null +++ b/src/ol/renderer/webgl/webglvectorlayerrenderer.js @@ -0,0 +1,266 @@ +goog.provide('ol.renderer.webgl.VectorLayer'); + +goog.require('goog.array'); +goog.require('goog.asserts'); +goog.require('goog.events'); +goog.require('ol.ViewHint'); +goog.require('ol.extent'); +goog.require('ol.layer.Vector'); +goog.require('ol.render.webgl.ReplayGroup'); +goog.require('ol.renderer.vector'); +goog.require('ol.renderer.webgl.Layer'); +goog.require('ol.renderer.webgl.vectorlayer.shader'); +goog.require('ol.vec.Mat4'); + + + +/** + * @constructor + * @extends {ol.renderer.webgl.Layer} + * @param {ol.renderer.Map} mapRenderer Map renderer. + * @param {ol.layer.Vector} vectorLayer Vector layer. + */ +ol.renderer.webgl.VectorLayer = function(mapRenderer, vectorLayer) { + + goog.base(this, mapRenderer, vectorLayer); + + /** + * @private + * @type {ol.webgl.shader.Fragment} + */ + this.fragmentShader_ = + ol.renderer.webgl.vectorlayer.shader.Fragment.getInstance(); + + /** + * @private + * @type {ol.webgl.shader.Vertex} + */ + this.vertexShader_ = + ol.renderer.webgl.vectorlayer.shader.Vertex.getInstance(); + + /** + * @private + * @type {ol.renderer.webgl.vectorlayer.shader.Locations} + */ + this.locations_ = null; + + /** + * @private + * @type {boolean} + */ + this.dirty_ = false; + + /** + * @private + * @type {number} + */ + this.renderedRevision_ = -1; + + /** + * @private + * @type {number} + */ + this.renderedResolution_ = NaN; + + /** + * @private + * @type {ol.Extent} + */ + this.renderedExtent_ = ol.extent.createEmpty(); + + /** + * @private + * @type {function(ol.Feature, ol.Feature): number|null} + */ + this.renderedRenderOrder_ = null; + + /** + * @private + * @type {ol.render.webgl.ReplayGroup} + */ + this.replayGroup_ = null; + +}; +goog.inherits(ol.renderer.webgl.VectorLayer, ol.renderer.webgl.Layer); + + +/** + * @inheritDoc + */ +ol.renderer.webgl.VectorLayer.prototype.composeFrame = + function(frameState, layerState, context) { + + var gl = context.getGL(); + + var program = context.getProgram( + this.fragmentShader_, this.vertexShader_); + context.useProgram(program); + + if (goog.isNull(this.locations_)) { + this.locations_ = + new ol.renderer.webgl.vectorlayer.shader.Locations( + gl, program); + } + + var viewState = frameState.viewState; + ol.vec.Mat4.makeTransform2D(this.projectionMatrix, + 0.0, 0.0, + 2 / (viewState.resolution * frameState.size[0]), + 2 / (viewState.resolution * frameState.size[1]), + -viewState.rotation, + -viewState.center[0], -viewState.center[1]); + + var replayGroup = this.replayGroup_; + if (!goog.isNull(replayGroup) && !replayGroup.isEmpty()) { + replayGroup.replay(context, + this.locations_.a_position, + this.locations_.u_projectionMatrix, + frameState.extent, frameState.pixelRatio, + this.projectionMatrix, + frameState.skippedFeatureUids); + } + +}; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.VectorLayer.prototype.forEachFeatureAtPixel = + function(coordinate, frameState, callback, thisArg) { +}; + + +/** + * Handle changes in image style state. + * @param {goog.events.Event} event Image style change event. + * @private + */ +ol.renderer.webgl.VectorLayer.prototype.handleImageChange_ = + function(event) { + this.renderIfReadyAndVisible(); +}; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.VectorLayer.prototype.prepareFrame = + function(frameState, layerState, context) { + + var vectorLayer = /** @type {ol.layer.Vector} */ (this.getLayer()); + goog.asserts.assertInstanceof(vectorLayer, ol.layer.Vector); + var vectorSource = vectorLayer.getSource(); + + this.updateAttributions( + frameState.attributions, vectorSource.getAttributions()); + this.updateLogos(frameState, vectorSource); + + if (!this.dirty_ && (frameState.viewHints[ol.ViewHint.ANIMATING] || + frameState.viewHints[ol.ViewHint.INTERACTING])) { + return true; + } + + var frameStateExtent = frameState.extent; + var viewState = frameState.viewState; + var projection = viewState.projection; + var resolution = viewState.resolution; + var pixelRatio = frameState.pixelRatio; + var vectorLayerRevision = vectorLayer.getRevision(); + var vectorLayerRenderOrder = vectorLayer.getRenderOrder(); + if (!goog.isDef(vectorLayerRenderOrder)) { + vectorLayerRenderOrder = ol.renderer.vector.defaultOrder; + } + + if (!this.dirty_ && + this.renderedResolution_ == resolution && + this.renderedRevision_ == vectorLayerRevision && + this.renderedRenderOrder_ == vectorLayerRenderOrder && + ol.extent.containsExtent(this.renderedExtent_, frameStateExtent)) { + return true; + } + + var extent = this.renderedExtent_; + var xBuffer = ol.extent.getWidth(frameStateExtent) / 4; + var yBuffer = ol.extent.getHeight(frameStateExtent) / 4; + extent[0] = frameStateExtent[0] - xBuffer; + extent[1] = frameStateExtent[1] - yBuffer; + extent[2] = frameStateExtent[2] + xBuffer; + extent[3] = frameStateExtent[3] + yBuffer; + + // FIXME dispose of old replayGroup in post render + goog.dispose(this.replayGroup_); + this.replayGroup_ = null; + + this.dirty_ = false; + + var replayGroup = new ol.render.webgl.ReplayGroup( + ol.renderer.vector.getTolerance(resolution, pixelRatio)); + vectorSource.loadFeatures(extent, resolution, projection); + var renderFeature = + /** + * @param {ol.Feature} feature Feature. + * @this {ol.renderer.webgl.VectorLayer} + */ + function(feature) { + var styles; + if (goog.isDef(feature.getStyleFunction())) { + styles = feature.getStyleFunction().call(feature, resolution); + } else if (goog.isDef(vectorLayer.getStyleFunction())) { + styles = vectorLayer.getStyleFunction()(feature, resolution); + } + if (goog.isDefAndNotNull(styles)) { + var dirty = this.renderFeature( + feature, resolution, pixelRatio, styles, replayGroup); + this.dirty_ = this.dirty_ || dirty; + } + }; + if (!goog.isNull(vectorLayerRenderOrder)) { + /** @type {Array.} */ + var features = []; + vectorSource.forEachFeatureInExtentAtResolution(extent, resolution, + /** + * @param {ol.Feature} feature Feature. + */ + function(feature) { + features.push(feature); + }, this); + goog.array.sort(features, vectorLayerRenderOrder); + goog.array.forEach(features, renderFeature, this); + } else { + vectorSource.forEachFeatureInExtentAtResolution( + extent, resolution, renderFeature, this); + } + replayGroup.finish(context); + + this.renderedResolution_ = resolution; + this.renderedRevision_ = vectorLayerRevision; + this.renderedRenderOrder_ = vectorLayerRenderOrder; + this.replayGroup_ = replayGroup; + + return true; +}; + + +/** + * @param {ol.Feature} feature Feature. + * @param {number} resolution Resolution. + * @param {number} pixelRatio Pixel ratio. + * @param {Array.} styles Array of styles + * @param {ol.render.webgl.ReplayGroup} replayGroup Replay group. + * @return {boolean} `true` if an image is loading. + */ +ol.renderer.webgl.VectorLayer.prototype.renderFeature = + function(feature, resolution, pixelRatio, styles, replayGroup) { + if (!goog.isDefAndNotNull(styles)) { + return false; + } + var i, ii, loading = false; + for (i = 0, ii = styles.length; i < ii; ++i) { + loading = ol.renderer.vector.renderFeature( + replayGroup, feature, styles[i], + ol.renderer.vector.getSquaredTolerance(resolution, pixelRatio), + feature, this.handleImageChange_, this) || loading; + } + return loading; +}; diff --git a/src/ol/renderer/webgl/webglvectorlayershader.js b/src/ol/renderer/webgl/webglvectorlayershader.js new file mode 100644 index 0000000000..c5befe3852 --- /dev/null +++ b/src/ol/renderer/webgl/webglvectorlayershader.js @@ -0,0 +1,99 @@ +// This file is automatically generated, do not edit +goog.provide('ol.renderer.webgl.vectorlayer.shader'); + +goog.require('ol.webgl.shader'); + + + +/** + * @constructor + * @extends {ol.webgl.shader.Fragment} + * @struct + */ +ol.renderer.webgl.vectorlayer.shader.Fragment = function() { + goog.base(this, ol.renderer.webgl.vectorlayer.shader.Fragment.SOURCE); +}; +goog.inherits(ol.renderer.webgl.vectorlayer.shader.Fragment, ol.webgl.shader.Fragment); +goog.addSingletonGetter(ol.renderer.webgl.vectorlayer.shader.Fragment); + + +/** + * @const + * @type {string} + */ +ol.renderer.webgl.vectorlayer.shader.Fragment.DEBUG_SOURCE = 'precision mediump float;\n\n\n\nvoid main(void) {\n gl_FragColor = vec4(1.0, 1.0, 0.0, 0.7);\n}\n'; + + +/** + * @const + * @type {string} + */ +ol.renderer.webgl.vectorlayer.shader.Fragment.OPTIMIZED_SOURCE = 'precision mediump float;void main(void){gl_FragColor=vec4(1.0,1.0,0.0,0.7);}'; + + +/** + * @const + * @type {string} + */ +ol.renderer.webgl.vectorlayer.shader.Fragment.SOURCE = goog.DEBUG ? + ol.renderer.webgl.vectorlayer.shader.Fragment.DEBUG_SOURCE : + ol.renderer.webgl.vectorlayer.shader.Fragment.OPTIMIZED_SOURCE; + + + +/** + * @constructor + * @extends {ol.webgl.shader.Vertex} + * @struct + */ +ol.renderer.webgl.vectorlayer.shader.Vertex = function() { + goog.base(this, ol.renderer.webgl.vectorlayer.shader.Vertex.SOURCE); +}; +goog.inherits(ol.renderer.webgl.vectorlayer.shader.Vertex, ol.webgl.shader.Vertex); +goog.addSingletonGetter(ol.renderer.webgl.vectorlayer.shader.Vertex); + + +/** + * @const + * @type {string} + */ +ol.renderer.webgl.vectorlayer.shader.Vertex.DEBUG_SOURCE = '\n\nattribute vec2 a_position;\n\nuniform mat4 u_projectionMatrix;\n\nvoid main(void) {\n gl_PointSize = 10.0;\n gl_Position = u_projectionMatrix * vec4(a_position, 0., 1.);\n}\n\n\n'; + + +/** + * @const + * @type {string} + */ +ol.renderer.webgl.vectorlayer.shader.Vertex.OPTIMIZED_SOURCE = 'attribute vec2 a;uniform mat4 b;void main(void){gl_PointSize=10.0;gl_Position=b*vec4(a,0.,1.);}'; + + +/** + * @const + * @type {string} + */ +ol.renderer.webgl.vectorlayer.shader.Vertex.SOURCE = goog.DEBUG ? + ol.renderer.webgl.vectorlayer.shader.Vertex.DEBUG_SOURCE : + ol.renderer.webgl.vectorlayer.shader.Vertex.OPTIMIZED_SOURCE; + + + +/** + * @constructor + * @param {WebGLRenderingContext} gl GL. + * @param {WebGLProgram} program Program. + * @struct + */ +ol.renderer.webgl.vectorlayer.shader.Locations = function(gl, program) { + + /** + * @type {WebGLUniformLocation} + */ + this.u_projectionMatrix = gl.getUniformLocation( + program, goog.DEBUG ? 'u_projectionMatrix' : 'b'); + + /** + * @type {number} + */ + this.a_position = gl.getAttribLocation( + program, goog.DEBUG ? 'a_position' : 'a'); +};