diff --git a/examples/icon-sprite-webgl.js b/examples/icon-sprite-webgl.js index f8d9e219b3..33c48856ec 100644 --- a/examples/icon-sprite-webgl.js +++ b/examples/icon-sprite-webgl.js @@ -9,23 +9,26 @@ goog.require('ol.style.Style'); var iconInfo = [{ - size: [55, 55], offset: [0, 0], opacity: 1.0, + rotateWithView: true, + rotation: 0.0, scale: 1.0, - rotation: 0.0 + size: [55, 55] }, { - size: [55, 55], offset: [110, 86], opacity: 0.75, + rotateWithView: false, + rotation: Math.PI / 2.0, scale: 1.25, - rotation: Math.PI / 2.0 + size: [55, 55] }, { - size: [55, 86], offset: [55, 0], opacity: 0.5, + rotateWithView: true, + rotation: Math.PI / 3.0, scale: 1.5, - rotation: Math.PI / 3.0 + size: [55, 86] }]; var i; @@ -35,12 +38,13 @@ var icons = new Array(iconCount); for (i = 0; i < iconCount; ++i) { var info = iconInfo[i]; icons[i] = new ol.style.Icon({ - src: 'data/Butterfly.png', - size: info.size, offset: info.offset, opacity: info.opacity, + rotateWithView: info.rotateWithView, + rotation: info.rotation, scale: info.scale, - rotation: info.rotation + size: info.size, + src: 'data/Butterfly.png' }); } diff --git a/src/ol/render/webgl/webglimage.glsl b/src/ol/render/webgl/webglimage.glsl index 5098ac2a3f..d5f5db9191 100644 --- a/src/ol/render/webgl/webglimage.glsl +++ b/src/ol/render/webgl/webglimage.glsl @@ -11,13 +11,19 @@ attribute vec2 a_position; attribute vec2 a_texCoord; attribute vec2 a_offsets; attribute float a_opacity; +attribute float a_rotateWithView; uniform mat4 u_projectionMatrix; -uniform mat2 u_sizeMatrix; +uniform mat4 u_offsetScaleMatrix; +uniform mat4 u_offsetRotateMatrix; void main(void) { - vec2 offsets = u_sizeMatrix * a_offsets; - gl_Position = u_projectionMatrix * vec4(a_position, 0., 1.) + vec4(offsets, 0., 0.); + mat4 offsetMatrix = u_offsetScaleMatrix; + if (a_rotateWithView == 1.0) { + offsetMatrix = u_offsetScaleMatrix * u_offsetRotateMatrix; + } + vec4 offsets = offsetMatrix * vec4(a_offsets, 0., 0.); + gl_Position = u_projectionMatrix * vec4(a_position, 0., 1.) + offsets; v_texCoord = a_texCoord; v_opacity = a_opacity; } diff --git a/src/ol/render/webgl/webglimageshader.js b/src/ol/render/webgl/webglimageshader.js index f50e358d84..69d59a09ce 100644 --- a/src/ol/render/webgl/webglimageshader.js +++ b/src/ol/render/webgl/webglimageshader.js @@ -28,7 +28,7 @@ ol.render.webgl.imagereplay.shader.Fragment.DEBUG_SOURCE = 'precision mediump fl * @const * @type {string} */ -ol.render.webgl.imagereplay.shader.Fragment.OPTIMIZED_SOURCE = 'precision mediump float;varying vec2 a;varying float b;uniform sampler2D i;void main(void){vec4 texColor=texture2D(i,a);gl_FragColor.rgb=texColor.rgb;gl_FragColor.a=texColor.a*b;}'; +ol.render.webgl.imagereplay.shader.Fragment.OPTIMIZED_SOURCE = 'precision mediump float;varying vec2 a;varying float b;uniform sampler2D k;void main(void){vec4 texColor=texture2D(k,a);gl_FragColor.rgb=texColor.rgb;gl_FragColor.a=texColor.a*b;}'; /** @@ -57,14 +57,14 @@ goog.addSingletonGetter(ol.render.webgl.imagereplay.shader.Vertex); * @const * @type {string} */ -ol.render.webgl.imagereplay.shader.Vertex.DEBUG_SOURCE = 'varying vec2 v_texCoord;\nvarying float v_opacity;\n\nattribute vec2 a_position;\nattribute vec2 a_texCoord;\nattribute vec2 a_offsets;\nattribute float a_opacity;\n\nuniform mat4 u_projectionMatrix;\nuniform mat2 u_sizeMatrix;\n\nvoid main(void) {\n vec2 offsets = u_sizeMatrix * a_offsets;\n gl_Position = u_projectionMatrix * vec4(a_position, 0., 1.) + vec4(offsets, 0., 0.);\n v_texCoord = a_texCoord;\n v_opacity = a_opacity;\n}\n\n\n'; +ol.render.webgl.imagereplay.shader.Vertex.DEBUG_SOURCE = 'varying vec2 v_texCoord;\nvarying float v_opacity;\n\nattribute vec2 a_position;\nattribute vec2 a_texCoord;\nattribute vec2 a_offsets;\nattribute float a_opacity;\nattribute float a_rotateWithView;\n\nuniform mat4 u_projectionMatrix;\nuniform mat4 u_offsetScaleMatrix;\nuniform mat4 u_offsetRotateMatrix;\n\nvoid main(void) {\n mat4 offsetMatrix = u_offsetScaleMatrix;\n if (a_rotateWithView == 1.0) {\n offsetMatrix = u_offsetScaleMatrix * u_offsetRotateMatrix;\n }\n vec4 offsets = offsetMatrix * vec4(a_offsets, 0., 0.);\n gl_Position = u_projectionMatrix * vec4(a_position, 0., 1.) + offsets;\n v_texCoord = a_texCoord;\n v_opacity = a_opacity;\n}\n\n\n'; /** * @const * @type {string} */ -ol.render.webgl.imagereplay.shader.Vertex.OPTIMIZED_SOURCE = 'varying vec2 a;varying float b;attribute vec2 c;attribute vec2 d;attribute vec2 e;attribute float f;uniform mat4 g;uniform mat2 h;void main(void){vec2 offsets=h*e;gl_Position=g*vec4(c,0.,1.)+vec4(offsets,0.,0.);a=d;b=f;}'; +ol.render.webgl.imagereplay.shader.Vertex.OPTIMIZED_SOURCE = 'varying vec2 a;varying float b;attribute vec2 c;attribute vec2 d;attribute vec2 e;attribute float f;attribute float g;uniform mat4 h;uniform mat4 i;uniform mat4 j;void main(void){mat4 offsetMatrix=i;if(g==1.0){offsetMatrix=i*j;}vec4 offsets=offsetMatrix*vec4(e,0.,0.);gl_Position=h*vec4(c,0.,1.)+offsets;a=d;b=f;}'; /** @@ -89,19 +89,25 @@ ol.render.webgl.imagereplay.shader.Locations = function(gl, program) { * @type {WebGLUniformLocation} */ this.u_image = gl.getUniformLocation( - program, goog.DEBUG ? 'u_image' : 'i'); + program, goog.DEBUG ? 'u_image' : 'k'); + + /** + * @type {WebGLUniformLocation} + */ + this.u_offsetRotateMatrix = gl.getUniformLocation( + program, goog.DEBUG ? 'u_offsetRotateMatrix' : 'j'); + + /** + * @type {WebGLUniformLocation} + */ + this.u_offsetScaleMatrix = gl.getUniformLocation( + program, goog.DEBUG ? 'u_offsetScaleMatrix' : 'i'); /** * @type {WebGLUniformLocation} */ this.u_projectionMatrix = gl.getUniformLocation( - program, goog.DEBUG ? 'u_projectionMatrix' : 'g'); - - /** - * @type {WebGLUniformLocation} - */ - this.u_sizeMatrix = gl.getUniformLocation( - program, goog.DEBUG ? 'u_sizeMatrix' : 'h'); + program, goog.DEBUG ? 'u_projectionMatrix' : 'h'); /** * @type {number} @@ -121,6 +127,12 @@ ol.render.webgl.imagereplay.shader.Locations = function(gl, program) { this.a_position = gl.getAttribLocation( program, goog.DEBUG ? 'a_position' : 'c'); + /** + * @type {number} + */ + this.a_rotateWithView = gl.getAttribLocation( + program, goog.DEBUG ? 'a_rotateWithView' : 'g'); + /** * @type {number} */ diff --git a/src/ol/render/webgl/webglreplay.js b/src/ol/render/webgl/webglreplay.js index d01a4b777e..9a6ac203a0 100644 --- a/src/ol/render/webgl/webglreplay.js +++ b/src/ol/render/webgl/webglreplay.js @@ -110,6 +110,18 @@ ol.render.webgl.ImageReplay = function(tolerance, maxExtent) { */ this.opacity_ = undefined; + /** + * @type {!goog.vec.Mat4.Number} + * @private + */ + this.offsetRotateMatrix_ = goog.vec.Mat4.createNumberIdentity(); + + /** + * @type {!goog.vec.Mat4.Number} + * @private + */ + this.offsetScaleMatrix_ = goog.vec.Mat4.createNumberIdentity(); + /** * @type {number|undefined} * @private @@ -128,6 +140,12 @@ ol.render.webgl.ImageReplay = function(tolerance, maxExtent) { */ this.projectionMatrix_ = goog.vec.Mat4.createNumberIdentity(); + /** + * @private + * @type {boolean|undefined} + */ + this.rotateWithView_ = undefined; + /** * @private * @type {number|undefined} @@ -222,6 +240,7 @@ ol.render.webgl.ImageReplay.prototype.drawCoordinates_ = goog.asserts.assert(goog.isDef(this.opacity_)); goog.asserts.assert(goog.isDef(this.originX_)); goog.asserts.assert(goog.isDef(this.originY_)); + goog.asserts.assert(goog.isDef(this.rotateWithView_)); goog.asserts.assert(goog.isDef(this.rotation_)); goog.asserts.assert(goog.isDef(this.scale_)); goog.asserts.assert(goog.isDef(this.width_)); @@ -233,6 +252,7 @@ ol.render.webgl.ImageReplay.prototype.drawCoordinates_ = var opacity = this.opacity_; var originX = this.originX_; var originY = this.originY_; + var rotateWithView = this.rotateWithView_ ? 1.0 : 0.0; var rotation = this.rotation_; var scale = this.scale_; var width = this.width_; @@ -245,9 +265,9 @@ ol.render.webgl.ImageReplay.prototype.drawCoordinates_ = x = flatCoordinates[i] - this.origin_[0]; y = flatCoordinates[i + 1] - this.origin_[1]; - n = numVertices / 7; + n = numVertices / 8; - // 4 vertices per coordinate, with 7 values per vertex + // 4 vertices per coordinate, with 8 values per vertex offsetX = -scale * anchorX; offsetY = -scale * (height - anchorY); @@ -258,6 +278,7 @@ ol.render.webgl.ImageReplay.prototype.drawCoordinates_ = this.vertices_[numVertices++] = (originX + width) / imageWidth; this.vertices_[numVertices++] = (originY + height) / imageHeight; this.vertices_[numVertices++] = opacity; + this.vertices_[numVertices++] = rotateWithView; offsetX = scale * (width - anchorX); offsetY = -scale * (height - anchorY); @@ -268,6 +289,7 @@ ol.render.webgl.ImageReplay.prototype.drawCoordinates_ = this.vertices_[numVertices++] = originX / imageWidth; this.vertices_[numVertices++] = (originY + height) / imageHeight; this.vertices_[numVertices++] = opacity; + this.vertices_[numVertices++] = rotateWithView; offsetX = scale * (width - anchorX); offsetY = scale * anchorY; @@ -278,6 +300,7 @@ ol.render.webgl.ImageReplay.prototype.drawCoordinates_ = this.vertices_[numVertices++] = originX / imageWidth; this.vertices_[numVertices++] = originY / imageHeight; this.vertices_[numVertices++] = opacity; + this.vertices_[numVertices++] = rotateWithView; offsetX = -scale * anchorX; offsetY = scale * anchorY; @@ -288,6 +311,7 @@ ol.render.webgl.ImageReplay.prototype.drawCoordinates_ = this.vertices_[numVertices++] = (originX + width) / imageWidth; this.vertices_[numVertices++] = originY / imageHeight; this.vertices_[numVertices++] = opacity; + this.vertices_[numVertices++] = rotateWithView; this.indices_[numIndices++] = n; this.indices_[numIndices++] = n + 1; @@ -431,6 +455,7 @@ ol.render.webgl.ImageReplay.prototype.finish = function(context) { this.opacity_ = undefined; this.originX_ = undefined; this.originY_ = undefined; + this.rotateWithView_ = undefined; this.rotation_ = undefined; this.scale_ = undefined; this.vertices_ = null; @@ -481,29 +506,43 @@ ol.render.webgl.ImageReplay.prototype.replay = function(context, -rotation, -(center[0] - this.origin_[0]), -(center[1] - this.origin_[1])); + var offsetScaleMatrix = this.offsetScaleMatrix_; + goog.vec.Mat4.makeScale(offsetScaleMatrix, 2 / size[0], 2 / size[1], 1); + + var offsetRotateMatrix = this.offsetRotateMatrix_; + goog.vec.Mat4.makeIdentity(offsetRotateMatrix); + if (rotation !== 0) { + goog.vec.Mat4.rotateZ(offsetRotateMatrix, -rotation); + } + var locations = this.locations_; gl.bindBuffer(goog.webgl.ARRAY_BUFFER, this.verticesBuffer_); gl.enableVertexAttribArray(locations.a_position); gl.vertexAttribPointer(locations.a_position, 2, goog.webgl.FLOAT, - false, 28, 0); + false, 32, 0); gl.enableVertexAttribArray(locations.a_offsets); gl.vertexAttribPointer(locations.a_offsets, 2, goog.webgl.FLOAT, - false, 28, 8); + false, 32, 8); gl.enableVertexAttribArray(locations.a_texCoord); gl.vertexAttribPointer(locations.a_texCoord, 2, goog.webgl.FLOAT, - false, 28, 16); + false, 32, 16); gl.enableVertexAttribArray(locations.a_opacity); gl.vertexAttribPointer(locations.a_opacity, 1, goog.webgl.FLOAT, - false, 28, 24); + false, 32, 24); + + gl.enableVertexAttribArray(locations.a_rotateWithView); + gl.vertexAttribPointer(locations.a_rotateWithView, 1, goog.webgl.FLOAT, + false, 32, 28); gl.uniformMatrix4fv(locations.u_projectionMatrix, false, projectionMatrix); - gl.uniformMatrix2fv(locations.u_sizeMatrix, false, - new Float32Array([2 / size[0], 0.0, 0.0, 2 / size[1]])); + gl.uniformMatrix4fv(locations.u_offsetScaleMatrix, false, offsetScaleMatrix); + gl.uniformMatrix4fv(locations.u_offsetRotateMatrix, false, + offsetRotateMatrix); gl.bindBuffer(goog.webgl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer_); @@ -540,6 +579,8 @@ ol.render.webgl.ImageReplay.prototype.setImageStyle = function(imageStyle) { goog.asserts.assert(goog.isDef(opacity)); var origin = imageStyle.getOrigin(); goog.asserts.assert(!goog.isNull(origin)); + var rotateWithView = imageStyle.getRotateWithView(); + goog.asserts.assert(goog.isDef(rotateWithView)); var rotation = imageStyle.getRotation(); goog.asserts.assert(goog.isDef(rotation)); var size = imageStyle.getSize(); @@ -567,6 +608,7 @@ ol.render.webgl.ImageReplay.prototype.setImageStyle = function(imageStyle) { this.originX_ = origin[0]; this.originY_ = origin[1]; this.rotation_ = rotation; + this.rotateWithView_ = rotateWithView; this.scale_ = scale; this.width_ = size[0]; };