From c8225e49b137653f49e1b8789ee14214122b031b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Thu, 23 Oct 2014 15:29:28 +0200 Subject: [PATCH] Use triangles to draw points with WebGL --- src/ol/render/webgl/webglreplay.js | 118 +++++++++++++----- src/ol/renderer/webgl/webglvectorlayer.glsl | 7 +- .../webgl/webglvectorlayerrenderer.js | 1 + .../renderer/webgl/webglvectorlayershader.js | 16 ++- 4 files changed, 105 insertions(+), 37 deletions(-) diff --git a/src/ol/render/webgl/webglreplay.js b/src/ol/render/webgl/webglreplay.js index 849a87e848..c86225faf7 100644 --- a/src/ol/render/webgl/webglreplay.js +++ b/src/ol/render/webgl/webglreplay.js @@ -21,13 +21,25 @@ ol.render.webgl.Replay = function(tolerance) { * @protected * @type {Array.} */ - this.coordinates = []; + this.vertices = []; + + /** + * @protected + * @type {Array.} + */ + this.indices = []; /** * @protected * @type {WebGLBuffer} */ - this.buffer = null; + this.verticesBuffer = null; + + /** + * @protected + * @type {WebGLBuffer} + */ + this.indicesBuffer = null; /** * @private @@ -44,22 +56,57 @@ ol.render.webgl.Replay = function(tolerance) { * @param {number} end End. * @param {number} stride Stride. * @param {boolean} close Close. - * @protected * @return {number} My end. + * @protected */ ol.render.webgl.Replay.prototype.appendFlatCoordinates = function(flatCoordinates, offset, end, stride, close) { - var myEnd = this.coordinates.length; - var i; + var numIndices = this.indices.length; + var numVertices = this.vertices.length; + var i, x, y, n; + var oy = 0.05; + var ox = 0.01; for (i = offset; i < end; i += stride) { - this.coordinates[myEnd++] = flatCoordinates[i]; - this.coordinates[myEnd++] = flatCoordinates[i + 1]; + x = flatCoordinates[i]; + y = flatCoordinates[i + 1]; + + n = numVertices / 4; + + // create 4 vertices per coordinate + + this.vertices[numVertices++] = x; + this.vertices[numVertices++] = y; + this.vertices[numVertices++] = -ox; + this.vertices[numVertices++] = -oy; + + this.vertices[numVertices++] = x; + this.vertices[numVertices++] = y; + this.vertices[numVertices++] = ox; + this.vertices[numVertices++] = -oy; + + this.vertices[numVertices++] = x; + this.vertices[numVertices++] = y; + this.vertices[numVertices++] = ox; + this.vertices[numVertices++] = oy; + + this.vertices[numVertices++] = x; + this.vertices[numVertices++] = y; + this.vertices[numVertices++] = -ox; + this.vertices[numVertices++] = oy; + + this.indices[numIndices++] = n; + this.indices[numIndices++] = n + 1; + this.indices[numIndices++] = n + 2; + this.indices[numIndices++] = n; + this.indices[numIndices++] = n + 2; + this.indices[numIndices++] = n + 3; } + if (close) { - this.coordinates[myEnd++] = flatCoordinates[offset]; - this.coordinates[myEnd++] = flatCoordinates[offset + 1]; + // FIXME + goog.asserts.fail(); } - return myEnd; + return numVertices; }; @@ -71,7 +118,8 @@ ol.render.webgl.Replay.prototype.finish = goog.nullFunction; /** * @param {ol.webgl.Context} context Context. - * @param {number} attribLocation Attribute location. + * @param {number} positionAttribLocation Attribute location for positions. + * @param {number} offsetsAttribLocation Attribute location for offsets. * @param {WebGLUniformLocation} projectionMatrixLocation Projection * matrix location. * @param {number} pixelRatio Pixel ratio. @@ -81,16 +129,23 @@ ol.render.webgl.Replay.prototype.finish = goog.nullFunction; * @template T */ ol.render.webgl.Replay.prototype.replay = - function(context, attribLocation, projectionMatrixLocation, - pixelRatio, transform, skippedFeaturesHash) { + function(context, positionAttribLocation, offsetsAttribLocation, + 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); + + gl.bindBuffer(goog.webgl.ARRAY_BUFFER, this.verticesBuffer); + gl.enableVertexAttribArray(positionAttribLocation); + gl.vertexAttribPointer(positionAttribLocation, 2, goog.webgl.FLOAT, + false, 16, 0); + gl.enableVertexAttribArray(offsetsAttribLocation); + gl.vertexAttribPointer(offsetsAttribLocation, 2, goog.webgl.FLOAT, + false, 16, 8); + + gl.bindBuffer(goog.webgl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer); + gl.uniformMatrix4fv(projectionMatrixLocation, false, transform); + gl.drawElements(goog.webgl.TRIANGLES, this.indices.length, + goog.webgl.UNSIGNED_SHORT, 0); }; @@ -243,10 +298,14 @@ ol.render.webgl.ImageReplay.prototype.drawMultiPointGeometry = */ ol.render.webgl.ImageReplay.prototype.finish = function(context) { var gl = context.getGL(); - this.buffer = gl.createBuffer(); - gl.bindBuffer(goog.webgl.ARRAY_BUFFER, this.buffer); + this.verticesBuffer = gl.createBuffer(); + gl.bindBuffer(goog.webgl.ARRAY_BUFFER, this.verticesBuffer); gl.bufferData(goog.webgl.ARRAY_BUFFER, - new Float32Array(this.coordinates), goog.webgl.STATIC_DRAW); + new Float32Array(this.vertices), goog.webgl.STATIC_DRAW); + this.indicesBuffer = gl.createBuffer(); + gl.bindBuffer(goog.webgl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer); + gl.bufferData(goog.webgl.ELEMENT_ARRAY_BUFFER, + new Uint16Array(this.indices), goog.webgl.STATIC_DRAW); }; @@ -326,7 +385,8 @@ ol.render.webgl.ReplayGroup.prototype.isEmpty = function() { /** * @param {ol.webgl.Context} context Context. - * @param {number} attribLocation Attribute location. + * @param {number} positionAttribLocation Attribute location for positions. + * @param {number} offsetsAttribLocation Attribute location for offsets. * @param {WebGLUniformLocation} projectionMatrixLocation Projection * matrix location. * @param {ol.Extent} extent Extent. @@ -337,16 +397,18 @@ ol.render.webgl.ReplayGroup.prototype.isEmpty = function() { * @template T */ ol.render.webgl.ReplayGroup.prototype.replay = function( - context, attribLocation, projectionMatrixLocation, extent, - pixelRatio, transform, skippedFeaturesHash) { + context, positionAttribLocation, offsetsAttribLocation, + 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); + context, positionAttribLocation, offsetsAttribLocation, + projectionMatrixLocation, pixelRatio, transform, + skippedFeaturesHash); if (result) { return result; } diff --git a/src/ol/renderer/webgl/webglvectorlayer.glsl b/src/ol/renderer/webgl/webglvectorlayer.glsl index cc8aaf7dc2..1154bf2fb3 100644 --- a/src/ol/renderer/webgl/webglvectorlayer.glsl +++ b/src/ol/renderer/webgl/webglvectorlayer.glsl @@ -4,20 +4,19 @@ //! COMMON - //! VERTEX attribute vec2 a_position; +attribute vec2 a_offsets; uniform mat4 u_projectionMatrix; void main(void) { - gl_PointSize = 10.0; - gl_Position = u_projectionMatrix * vec4(a_position, 0., 1.); + gl_Position = u_projectionMatrix * vec4(a_position, 0., 1.) + vec4(a_offsets, 0., 0.); } //! FRAGMENT void main(void) { - gl_FragColor = vec4(1.0, 1.0, 0.0, 0.7); + gl_FragColor = vec4(1.0, 1.0, 0.0, 1); } diff --git a/src/ol/renderer/webgl/webglvectorlayerrenderer.js b/src/ol/renderer/webgl/webglvectorlayerrenderer.js index ef285cfde0..a85b6d1efc 100644 --- a/src/ol/renderer/webgl/webglvectorlayerrenderer.js +++ b/src/ol/renderer/webgl/webglvectorlayerrenderer.js @@ -114,6 +114,7 @@ ol.renderer.webgl.VectorLayer.prototype.composeFrame = if (!goog.isNull(replayGroup) && !replayGroup.isEmpty()) { replayGroup.replay(context, this.locations_.a_position, + this.locations_.a_offsets, this.locations_.u_projectionMatrix, frameState.extent, frameState.pixelRatio, this.projectionMatrix, diff --git a/src/ol/renderer/webgl/webglvectorlayershader.js b/src/ol/renderer/webgl/webglvectorlayershader.js index c5befe3852..4559a8a4fe 100644 --- a/src/ol/renderer/webgl/webglvectorlayershader.js +++ b/src/ol/renderer/webgl/webglvectorlayershader.js @@ -21,14 +21,14 @@ 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'; +ol.renderer.webgl.vectorlayer.shader.Fragment.DEBUG_SOURCE = 'precision mediump float;\n\n\nvoid main(void) {\n gl_FragColor = vec4(1.0, 1.0, 0.0, 1);\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);}'; +ol.renderer.webgl.vectorlayer.shader.Fragment.OPTIMIZED_SOURCE = 'precision mediump float;void main(void){gl_FragColor=vec4(1.0,1.0,0.0,1);}'; /** @@ -57,14 +57,14 @@ 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'; +ol.renderer.webgl.vectorlayer.shader.Vertex.DEBUG_SOURCE = '\nattribute vec2 a_position;\nattribute vec2 a_offsets;\n\nuniform mat4 u_projectionMatrix;\n\nvoid main(void) {\n gl_Position = u_projectionMatrix * vec4(a_position, 0., 1.) + vec4(a_offsets, 0., 0.);\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.);}'; +ol.renderer.webgl.vectorlayer.shader.Vertex.OPTIMIZED_SOURCE = 'attribute vec2 a;attribute vec2 b;uniform mat4 c;void main(void){gl_Position=c*vec4(a,0.,1.)+vec4(b,0.,0.);}'; /** @@ -89,7 +89,13 @@ ol.renderer.webgl.vectorlayer.shader.Locations = function(gl, program) { * @type {WebGLUniformLocation} */ this.u_projectionMatrix = gl.getUniformLocation( - program, goog.DEBUG ? 'u_projectionMatrix' : 'b'); + program, goog.DEBUG ? 'u_projectionMatrix' : 'c'); + + /** + * @type {number} + */ + this.a_offsets = gl.getAttribLocation( + program, goog.DEBUG ? 'a_offsets' : 'b'); /** * @type {number}