From 1de46c68d75b0cdcbb016092fb5a809ae05073e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Mon, 10 Nov 2014 13:54:04 +0100 Subject: [PATCH 1/3] Use "discard" in image shader This leads to better looking Timeline profiles in Chrome's developer tools! --- src/ol/render/webgl/webglimage.glsl | 6 +++++- src/ol/render/webgl/webglimageshader.js | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/ol/render/webgl/webglimage.glsl b/src/ol/render/webgl/webglimage.glsl index d5f5db9191..8339467ca6 100644 --- a/src/ol/render/webgl/webglimage.glsl +++ b/src/ol/render/webgl/webglimage.glsl @@ -35,5 +35,9 @@ uniform sampler2D u_image; void main(void) { vec4 texColor = texture2D(u_image, v_texCoord); gl_FragColor.rgb = texColor.rgb; - gl_FragColor.a = texColor.a * v_opacity; + float alpha = texColor.a * v_opacity; + if (alpha == 0.0) { + discard; + } + gl_FragColor.a = alpha; } diff --git a/src/ol/render/webgl/webglimageshader.js b/src/ol/render/webgl/webglimageshader.js index 69d59a09ce..35f2b6f93e 100644 --- a/src/ol/render/webgl/webglimageshader.js +++ b/src/ol/render/webgl/webglimageshader.js @@ -21,14 +21,14 @@ goog.addSingletonGetter(ol.render.webgl.imagereplay.shader.Fragment); * @const * @type {string} */ -ol.render.webgl.imagereplay.shader.Fragment.DEBUG_SOURCE = 'precision mediump float;\nvarying vec2 v_texCoord;\nvarying float v_opacity;\n\nuniform sampler2D u_image;\n\nvoid main(void) {\n vec4 texColor = texture2D(u_image, v_texCoord);\n gl_FragColor.rgb = texColor.rgb;\n gl_FragColor.a = texColor.a * v_opacity;\n}\n'; +ol.render.webgl.imagereplay.shader.Fragment.DEBUG_SOURCE = 'precision mediump float;\nvarying vec2 v_texCoord;\nvarying float v_opacity;\n\nuniform sampler2D u_image;\n\nvoid main(void) {\n vec4 texColor = texture2D(u_image, v_texCoord);\n gl_FragColor.rgb = texColor.rgb;\n float alpha = texColor.a * v_opacity;\n if (alpha == 0.0) {\n discard;\n }\n gl_FragColor.a = alpha;\n}\n'; /** * @const * @type {string} */ -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;}'; +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;float alpha=texColor.a*b;if(alpha==0.0){discard;}gl_FragColor.a=alpha;}'; /** From 240f425c4638bbf4c663220b619e42f72ead2490 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Mon, 10 Nov 2014 14:08:44 +0100 Subject: [PATCH 2/3] =?UTF-8?q?Add=20global=20opacity=20support=20to=20Web?= =?UTF-8?q?GL=C2=A0image=20replay?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vectorLayer.setOpacity() now works as expected. --- src/ol/render/webgl/webglimage.glsl | 3 ++- src/ol/render/webgl/webglimageshader.js | 12 +++++++++--- src/ol/render/webgl/webglreplay.js | 9 ++++++--- src/ol/renderer/webgl/webglmaprenderer.js | 3 ++- src/ol/renderer/webgl/webglvectorlayerrenderer.js | 1 + 5 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/ol/render/webgl/webglimage.glsl b/src/ol/render/webgl/webglimage.glsl index 8339467ca6..62e7adf6cf 100644 --- a/src/ol/render/webgl/webglimage.glsl +++ b/src/ol/render/webgl/webglimage.glsl @@ -30,12 +30,13 @@ void main(void) { //! FRAGMENT +uniform float u_opacity; uniform sampler2D u_image; void main(void) { vec4 texColor = texture2D(u_image, v_texCoord); gl_FragColor.rgb = texColor.rgb; - float alpha = texColor.a * v_opacity; + float alpha = texColor.a * v_opacity * u_opacity; if (alpha == 0.0) { discard; } diff --git a/src/ol/render/webgl/webglimageshader.js b/src/ol/render/webgl/webglimageshader.js index 35f2b6f93e..1cfc0e2fae 100644 --- a/src/ol/render/webgl/webglimageshader.js +++ b/src/ol/render/webgl/webglimageshader.js @@ -21,14 +21,14 @@ goog.addSingletonGetter(ol.render.webgl.imagereplay.shader.Fragment); * @const * @type {string} */ -ol.render.webgl.imagereplay.shader.Fragment.DEBUG_SOURCE = 'precision mediump float;\nvarying vec2 v_texCoord;\nvarying float v_opacity;\n\nuniform sampler2D u_image;\n\nvoid main(void) {\n vec4 texColor = texture2D(u_image, v_texCoord);\n gl_FragColor.rgb = texColor.rgb;\n float alpha = texColor.a * v_opacity;\n if (alpha == 0.0) {\n discard;\n }\n gl_FragColor.a = alpha;\n}\n'; +ol.render.webgl.imagereplay.shader.Fragment.DEBUG_SOURCE = 'precision mediump float;\nvarying vec2 v_texCoord;\nvarying float v_opacity;\n\nuniform float u_opacity;\nuniform sampler2D u_image;\n\nvoid main(void) {\n vec4 texColor = texture2D(u_image, v_texCoord);\n gl_FragColor.rgb = texColor.rgb;\n float alpha = texColor.a * v_opacity * u_opacity;\n if (alpha == 0.0) {\n discard;\n }\n gl_FragColor.a = alpha;\n}\n'; /** * @const * @type {string} */ -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;float alpha=texColor.a*b;if(alpha==0.0){discard;}gl_FragColor.a=alpha;}'; +ol.render.webgl.imagereplay.shader.Fragment.OPTIMIZED_SOURCE = 'precision mediump float;varying vec2 a;varying float b;uniform float k;uniform sampler2D l;void main(void){vec4 texColor=texture2D(l,a);gl_FragColor.rgb=texColor.rgb;float alpha=texColor.a*b*k;if(alpha==0.0){discard;}gl_FragColor.a=alpha;}'; /** @@ -89,7 +89,7 @@ ol.render.webgl.imagereplay.shader.Locations = function(gl, program) { * @type {WebGLUniformLocation} */ this.u_image = gl.getUniformLocation( - program, goog.DEBUG ? 'u_image' : 'k'); + program, goog.DEBUG ? 'u_image' : 'l'); /** * @type {WebGLUniformLocation} @@ -103,6 +103,12 @@ ol.render.webgl.imagereplay.shader.Locations = function(gl, program) { this.u_offsetScaleMatrix = gl.getUniformLocation( program, goog.DEBUG ? 'u_offsetScaleMatrix' : 'i'); + /** + * @type {WebGLUniformLocation} + */ + this.u_opacity = gl.getUniformLocation( + program, goog.DEBUG ? 'u_opacity' : 'k'); + /** * @type {WebGLUniformLocation} */ diff --git a/src/ol/render/webgl/webglreplay.js b/src/ol/render/webgl/webglreplay.js index 823e2d9851..890a490b2b 100644 --- a/src/ol/render/webgl/webglreplay.js +++ b/src/ol/render/webgl/webglreplay.js @@ -501,13 +501,14 @@ ol.render.webgl.ImageReplay.prototype.getExtent = function() { * @param {ol.Size} size Size. * @param {ol.Extent} extent Extent. * @param {number} pixelRatio Pixel ratio. + * @param {number} opacity Global opacity. * @param {Object} skippedFeaturesHash Ids of features to skip. * @return {T|undefined} Callback result. * @template T */ ol.render.webgl.ImageReplay.prototype.replay = function(context, center, resolution, rotation, size, extent, pixelRatio, - skippedFeaturesHash) { + opacity, skippedFeaturesHash) { var gl = context.getGL(); var program = context.getProgram( @@ -566,6 +567,7 @@ ol.render.webgl.ImageReplay.prototype.replay = function(context, gl.uniformMatrix4fv(locations.u_offsetScaleMatrix, false, offsetScaleMatrix); gl.uniformMatrix4fv(locations.u_offsetRotateMatrix, false, offsetRotateMatrix); + gl.uniform1f(locations.u_opacity, opacity); goog.asserts.assert(!goog.isNull(this.indicesBuffer_)); gl.bindBuffer(goog.webgl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer_); @@ -732,13 +734,14 @@ ol.render.webgl.ReplayGroup.prototype.isEmpty = function() { * @param {ol.Size} size Size. * @param {ol.Extent} extent Extent. * @param {number} pixelRatio Pixel ratio. + * @param {number} opacity Global opacity. * @param {Object} skippedFeaturesHash Ids of features to skip. * @return {T|undefined} Callback result. * @template T */ ol.render.webgl.ReplayGroup.prototype.replay = function(context, center, resolution, rotation, size, extent, pixelRatio, - skippedFeaturesHash) { + opacity, 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]]; @@ -746,7 +749,7 @@ ol.render.webgl.ReplayGroup.prototype.replay = function(context, ol.extent.intersects(extent, replay.getExtent())) { result = replay.replay(context, center, resolution, rotation, size, extent, pixelRatio, - skippedFeaturesHash); + opacity, skippedFeaturesHash); if (result) { return result; } diff --git a/src/ol/renderer/webgl/webglmaprenderer.js b/src/ol/renderer/webgl/webglmaprenderer.js index 5dbdcac643..9ec83bf5cd 100644 --- a/src/ol/renderer/webgl/webglmaprenderer.js +++ b/src/ol/renderer/webgl/webglmaprenderer.js @@ -291,8 +291,9 @@ ol.renderer.webgl.Map.prototype.dispatchComposeEvent_ = var center = viewState.center; var rotation = viewState.rotation; var size = frameState.size; + var opacity = 1; replayGroup.replay(context, center, resolution, rotation, size, extent, - pixelRatio, {}); + pixelRatio, opacity, {}); } this.replayGroup = replayGroup; } diff --git a/src/ol/renderer/webgl/webglvectorlayerrenderer.js b/src/ol/renderer/webgl/webglvectorlayerrenderer.js index e82492797f..773fde46a2 100644 --- a/src/ol/renderer/webgl/webglvectorlayerrenderer.js +++ b/src/ol/renderer/webgl/webglvectorlayerrenderer.js @@ -73,6 +73,7 @@ ol.renderer.webgl.VectorLayer.prototype.composeFrame = replayGroup.replay(context, viewState.center, viewState.resolution, viewState.rotation, frameState.size, frameState.extent, frameState.pixelRatio, + layerState.opacity, frameState.skippedFeatureUids); } From 87865be9f42affaa9e8fcca660d8292f71e8bc65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Mon, 10 Nov 2014 14:48:42 +0100 Subject: [PATCH 3/3] =?UTF-8?q?Add=20"color"=20support=20to=20WebGL=C2=A0i?= =?UTF-8?q?mage=20replay?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds support for layer brightness, contrast, hue, saturation. --- src/ol/render/webgl/webglimagecolor.glsl | 46 ++++++ src/ol/render/webgl/webglimagecolorshader.js | 153 ++++++++++++++++++ ...webglimage.glsl => webglimagedefault.glsl} | 4 +- .../render/webgl/webglimagedefaultshader.js | 147 +++++++++++++++++ src/ol/render/webgl/webglimageshader.js | 147 ----------------- src/ol/render/webgl/webglreplay.js | 97 +++++++---- src/ol/renderer/webgl/webglmaprenderer.js | 7 +- .../webgl/webglvectorlayerrenderer.js | 4 +- 8 files changed, 424 insertions(+), 181 deletions(-) create mode 100644 src/ol/render/webgl/webglimagecolor.glsl create mode 100644 src/ol/render/webgl/webglimagecolorshader.js rename src/ol/render/webgl/{webglimage.glsl => webglimagedefault.glsl} (89%) create mode 100644 src/ol/render/webgl/webglimagedefaultshader.js delete mode 100644 src/ol/render/webgl/webglimageshader.js diff --git a/src/ol/render/webgl/webglimagecolor.glsl b/src/ol/render/webgl/webglimagecolor.glsl new file mode 100644 index 0000000000..56e045f402 --- /dev/null +++ b/src/ol/render/webgl/webglimagecolor.glsl @@ -0,0 +1,46 @@ +//! NAMESPACE=ol.render.webgl.imagereplay.shader.Color +//! CLASS=ol.render.webgl.imagereplay.shader.Color + + +//! COMMON +varying vec2 v_texCoord; +varying float v_opacity; + +//! VERTEX +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 mat4 u_offsetScaleMatrix; +uniform mat4 u_offsetRotateMatrix; + +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.); + gl_Position = u_projectionMatrix * vec4(a_position, 0., 1.) + offsets; + v_texCoord = a_texCoord; + v_opacity = a_opacity; +} + + +//! FRAGMENT +// @see https://svn.webkit.org/repository/webkit/trunk/Source/WebCore/platform/graphics/filters/skia/SkiaImageFilterBuilder.cpp +uniform mat4 u_colorMatrix; +uniform float u_opacity; +uniform sampler2D u_image; + +void main(void) { + vec4 texColor = texture2D(u_image, v_texCoord); + float alpha = texColor.a * v_opacity * u_opacity; + if (alpha == 0.0) { + discard; + } + gl_FragColor.a = alpha; + gl_FragColor.rgb = (u_colorMatrix * vec4(texColor.rgb, 1.)).rgb; +} diff --git a/src/ol/render/webgl/webglimagecolorshader.js b/src/ol/render/webgl/webglimagecolorshader.js new file mode 100644 index 0000000000..94f1b8a74b --- /dev/null +++ b/src/ol/render/webgl/webglimagecolorshader.js @@ -0,0 +1,153 @@ +// This file is automatically generated, do not edit +goog.provide('ol.render.webgl.imagereplay.shader.Color'); + +goog.require('ol.webgl.shader'); + + + +/** + * @constructor + * @extends {ol.webgl.shader.Fragment} + * @struct + */ +ol.render.webgl.imagereplay.shader.ColorFragment = function() { + goog.base(this, ol.render.webgl.imagereplay.shader.ColorFragment.SOURCE); +}; +goog.inherits(ol.render.webgl.imagereplay.shader.ColorFragment, ol.webgl.shader.Fragment); +goog.addSingletonGetter(ol.render.webgl.imagereplay.shader.ColorFragment); + + +/** + * @const + * @type {string} + */ +ol.render.webgl.imagereplay.shader.ColorFragment.DEBUG_SOURCE = 'precision mediump float;\nvarying vec2 v_texCoord;\nvarying float v_opacity;\n\n// @see https://svn.webkit.org/repository/webkit/trunk/Source/WebCore/platform/graphics/filters/skia/SkiaImageFilterBuilder.cpp\nuniform mat4 u_colorMatrix;\nuniform float u_opacity;\nuniform sampler2D u_image;\n\nvoid main(void) {\n vec4 texColor = texture2D(u_image, v_texCoord);\n float alpha = texColor.a * v_opacity * u_opacity;\n if (alpha == 0.0) {\n discard;\n }\n gl_FragColor.a = alpha;\n gl_FragColor.rgb = (u_colorMatrix * vec4(texColor.rgb, 1.)).rgb;\n}\n'; + + +/** + * @const + * @type {string} + */ +ol.render.webgl.imagereplay.shader.ColorFragment.OPTIMIZED_SOURCE = 'precision mediump float;varying vec2 a;varying float b;uniform mat4 k;uniform float l;uniform sampler2D m;void main(void){vec4 texColor=texture2D(m,a);float alpha=texColor.a*b*l;if(alpha==0.0){discard;}gl_FragColor.a=alpha;gl_FragColor.rgb=(k*vec4(texColor.rgb,1.)).rgb;}'; + + +/** + * @const + * @type {string} + */ +ol.render.webgl.imagereplay.shader.ColorFragment.SOURCE = goog.DEBUG ? + ol.render.webgl.imagereplay.shader.ColorFragment.DEBUG_SOURCE : + ol.render.webgl.imagereplay.shader.ColorFragment.OPTIMIZED_SOURCE; + + + +/** + * @constructor + * @extends {ol.webgl.shader.Vertex} + * @struct + */ +ol.render.webgl.imagereplay.shader.ColorVertex = function() { + goog.base(this, ol.render.webgl.imagereplay.shader.ColorVertex.SOURCE); +}; +goog.inherits(ol.render.webgl.imagereplay.shader.ColorVertex, ol.webgl.shader.Vertex); +goog.addSingletonGetter(ol.render.webgl.imagereplay.shader.ColorVertex); + + +/** + * @const + * @type {string} + */ +ol.render.webgl.imagereplay.shader.ColorVertex.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.ColorVertex.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;}'; + + +/** + * @const + * @type {string} + */ +ol.render.webgl.imagereplay.shader.ColorVertex.SOURCE = goog.DEBUG ? + ol.render.webgl.imagereplay.shader.ColorVertex.DEBUG_SOURCE : + ol.render.webgl.imagereplay.shader.ColorVertex.OPTIMIZED_SOURCE; + + + +/** + * @constructor + * @param {WebGLRenderingContext} gl GL. + * @param {WebGLProgram} program Program. + * @struct + */ +ol.render.webgl.imagereplay.shader.Color.Locations = function(gl, program) { + + /** + * @type {WebGLUniformLocation} + */ + this.u_colorMatrix = gl.getUniformLocation( + program, goog.DEBUG ? 'u_colorMatrix' : 'k'); + + /** + * @type {WebGLUniformLocation} + */ + this.u_image = gl.getUniformLocation( + program, goog.DEBUG ? 'u_image' : 'm'); + + /** + * @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_opacity = gl.getUniformLocation( + program, goog.DEBUG ? 'u_opacity' : 'l'); + + /** + * @type {WebGLUniformLocation} + */ + this.u_projectionMatrix = gl.getUniformLocation( + program, goog.DEBUG ? 'u_projectionMatrix' : 'h'); + + /** + * @type {number} + */ + this.a_offsets = gl.getAttribLocation( + program, goog.DEBUG ? 'a_offsets' : 'e'); + + /** + * @type {number} + */ + this.a_opacity = gl.getAttribLocation( + program, goog.DEBUG ? 'a_opacity' : 'f'); + + /** + * @type {number} + */ + 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} + */ + this.a_texCoord = gl.getAttribLocation( + program, goog.DEBUG ? 'a_texCoord' : 'd'); +}; diff --git a/src/ol/render/webgl/webglimage.glsl b/src/ol/render/webgl/webglimagedefault.glsl similarity index 89% rename from src/ol/render/webgl/webglimage.glsl rename to src/ol/render/webgl/webglimagedefault.glsl index 62e7adf6cf..15d2bce128 100644 --- a/src/ol/render/webgl/webglimage.glsl +++ b/src/ol/render/webgl/webglimagedefault.glsl @@ -1,5 +1,5 @@ -//! NAMESPACE=ol.render.webgl.imagereplay.shader -//! CLASS=ol.render.webgl.imagereplay.shader. +//! NAMESPACE=ol.render.webgl.imagereplay.shader.Default +//! CLASS=ol.render.webgl.imagereplay.shader.Default //! COMMON diff --git a/src/ol/render/webgl/webglimagedefaultshader.js b/src/ol/render/webgl/webglimagedefaultshader.js new file mode 100644 index 0000000000..7df0fe26c5 --- /dev/null +++ b/src/ol/render/webgl/webglimagedefaultshader.js @@ -0,0 +1,147 @@ +// This file is automatically generated, do not edit +goog.provide('ol.render.webgl.imagereplay.shader.Default'); + +goog.require('ol.webgl.shader'); + + + +/** + * @constructor + * @extends {ol.webgl.shader.Fragment} + * @struct + */ +ol.render.webgl.imagereplay.shader.DefaultFragment = function() { + goog.base(this, ol.render.webgl.imagereplay.shader.DefaultFragment.SOURCE); +}; +goog.inherits(ol.render.webgl.imagereplay.shader.DefaultFragment, ol.webgl.shader.Fragment); +goog.addSingletonGetter(ol.render.webgl.imagereplay.shader.DefaultFragment); + + +/** + * @const + * @type {string} + */ +ol.render.webgl.imagereplay.shader.DefaultFragment.DEBUG_SOURCE = 'precision mediump float;\nvarying vec2 v_texCoord;\nvarying float v_opacity;\n\nuniform float u_opacity;\nuniform sampler2D u_image;\n\nvoid main(void) {\n vec4 texColor = texture2D(u_image, v_texCoord);\n gl_FragColor.rgb = texColor.rgb;\n float alpha = texColor.a * v_opacity * u_opacity;\n if (alpha == 0.0) {\n discard;\n }\n gl_FragColor.a = alpha;\n}\n'; + + +/** + * @const + * @type {string} + */ +ol.render.webgl.imagereplay.shader.DefaultFragment.OPTIMIZED_SOURCE = 'precision mediump float;varying vec2 a;varying float b;uniform float k;uniform sampler2D l;void main(void){vec4 texColor=texture2D(l,a);gl_FragColor.rgb=texColor.rgb;float alpha=texColor.a*b*k;if(alpha==0.0){discard;}gl_FragColor.a=alpha;}'; + + +/** + * @const + * @type {string} + */ +ol.render.webgl.imagereplay.shader.DefaultFragment.SOURCE = goog.DEBUG ? + ol.render.webgl.imagereplay.shader.DefaultFragment.DEBUG_SOURCE : + ol.render.webgl.imagereplay.shader.DefaultFragment.OPTIMIZED_SOURCE; + + + +/** + * @constructor + * @extends {ol.webgl.shader.Vertex} + * @struct + */ +ol.render.webgl.imagereplay.shader.DefaultVertex = function() { + goog.base(this, ol.render.webgl.imagereplay.shader.DefaultVertex.SOURCE); +}; +goog.inherits(ol.render.webgl.imagereplay.shader.DefaultVertex, ol.webgl.shader.Vertex); +goog.addSingletonGetter(ol.render.webgl.imagereplay.shader.DefaultVertex); + + +/** + * @const + * @type {string} + */ +ol.render.webgl.imagereplay.shader.DefaultVertex.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.DefaultVertex.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;}'; + + +/** + * @const + * @type {string} + */ +ol.render.webgl.imagereplay.shader.DefaultVertex.SOURCE = goog.DEBUG ? + ol.render.webgl.imagereplay.shader.DefaultVertex.DEBUG_SOURCE : + ol.render.webgl.imagereplay.shader.DefaultVertex.OPTIMIZED_SOURCE; + + + +/** + * @constructor + * @param {WebGLRenderingContext} gl GL. + * @param {WebGLProgram} program Program. + * @struct + */ +ol.render.webgl.imagereplay.shader.Default.Locations = function(gl, program) { + + /** + * @type {WebGLUniformLocation} + */ + this.u_image = gl.getUniformLocation( + program, goog.DEBUG ? 'u_image' : 'l'); + + /** + * @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_opacity = gl.getUniformLocation( + program, goog.DEBUG ? 'u_opacity' : 'k'); + + /** + * @type {WebGLUniformLocation} + */ + this.u_projectionMatrix = gl.getUniformLocation( + program, goog.DEBUG ? 'u_projectionMatrix' : 'h'); + + /** + * @type {number} + */ + this.a_offsets = gl.getAttribLocation( + program, goog.DEBUG ? 'a_offsets' : 'e'); + + /** + * @type {number} + */ + this.a_opacity = gl.getAttribLocation( + program, goog.DEBUG ? 'a_opacity' : 'f'); + + /** + * @type {number} + */ + 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} + */ + this.a_texCoord = gl.getAttribLocation( + program, goog.DEBUG ? 'a_texCoord' : 'd'); +}; diff --git a/src/ol/render/webgl/webglimageshader.js b/src/ol/render/webgl/webglimageshader.js deleted file mode 100644 index 1cfc0e2fae..0000000000 --- a/src/ol/render/webgl/webglimageshader.js +++ /dev/null @@ -1,147 +0,0 @@ -// This file is automatically generated, do not edit -goog.provide('ol.render.webgl.imagereplay.shader'); - -goog.require('ol.webgl.shader'); - - - -/** - * @constructor - * @extends {ol.webgl.shader.Fragment} - * @struct - */ -ol.render.webgl.imagereplay.shader.Fragment = function() { - goog.base(this, ol.render.webgl.imagereplay.shader.Fragment.SOURCE); -}; -goog.inherits(ol.render.webgl.imagereplay.shader.Fragment, ol.webgl.shader.Fragment); -goog.addSingletonGetter(ol.render.webgl.imagereplay.shader.Fragment); - - -/** - * @const - * @type {string} - */ -ol.render.webgl.imagereplay.shader.Fragment.DEBUG_SOURCE = 'precision mediump float;\nvarying vec2 v_texCoord;\nvarying float v_opacity;\n\nuniform float u_opacity;\nuniform sampler2D u_image;\n\nvoid main(void) {\n vec4 texColor = texture2D(u_image, v_texCoord);\n gl_FragColor.rgb = texColor.rgb;\n float alpha = texColor.a * v_opacity * u_opacity;\n if (alpha == 0.0) {\n discard;\n }\n gl_FragColor.a = alpha;\n}\n'; - - -/** - * @const - * @type {string} - */ -ol.render.webgl.imagereplay.shader.Fragment.OPTIMIZED_SOURCE = 'precision mediump float;varying vec2 a;varying float b;uniform float k;uniform sampler2D l;void main(void){vec4 texColor=texture2D(l,a);gl_FragColor.rgb=texColor.rgb;float alpha=texColor.a*b*k;if(alpha==0.0){discard;}gl_FragColor.a=alpha;}'; - - -/** - * @const - * @type {string} - */ -ol.render.webgl.imagereplay.shader.Fragment.SOURCE = goog.DEBUG ? - ol.render.webgl.imagereplay.shader.Fragment.DEBUG_SOURCE : - ol.render.webgl.imagereplay.shader.Fragment.OPTIMIZED_SOURCE; - - - -/** - * @constructor - * @extends {ol.webgl.shader.Vertex} - * @struct - */ -ol.render.webgl.imagereplay.shader.Vertex = function() { - goog.base(this, ol.render.webgl.imagereplay.shader.Vertex.SOURCE); -}; -goog.inherits(ol.render.webgl.imagereplay.shader.Vertex, ol.webgl.shader.Vertex); -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;\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;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;}'; - - -/** - * @const - * @type {string} - */ -ol.render.webgl.imagereplay.shader.Vertex.SOURCE = goog.DEBUG ? - ol.render.webgl.imagereplay.shader.Vertex.DEBUG_SOURCE : - ol.render.webgl.imagereplay.shader.Vertex.OPTIMIZED_SOURCE; - - - -/** - * @constructor - * @param {WebGLRenderingContext} gl GL. - * @param {WebGLProgram} program Program. - * @struct - */ -ol.render.webgl.imagereplay.shader.Locations = function(gl, program) { - - /** - * @type {WebGLUniformLocation} - */ - this.u_image = gl.getUniformLocation( - program, goog.DEBUG ? 'u_image' : 'l'); - - /** - * @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_opacity = gl.getUniformLocation( - program, goog.DEBUG ? 'u_opacity' : 'k'); - - /** - * @type {WebGLUniformLocation} - */ - this.u_projectionMatrix = gl.getUniformLocation( - program, goog.DEBUG ? 'u_projectionMatrix' : 'h'); - - /** - * @type {number} - */ - this.a_offsets = gl.getAttribLocation( - program, goog.DEBUG ? 'a_offsets' : 'e'); - - /** - * @type {number} - */ - this.a_opacity = gl.getAttribLocation( - program, goog.DEBUG ? 'a_opacity' : 'f'); - - /** - * @type {number} - */ - 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} - */ - this.a_texCoord = gl.getAttribLocation( - program, goog.DEBUG ? 'a_texCoord' : 'd'); -}; diff --git a/src/ol/render/webgl/webglreplay.js b/src/ol/render/webgl/webglreplay.js index 890a490b2b..b5d520c1eb 100644 --- a/src/ol/render/webgl/webglreplay.js +++ b/src/ol/render/webgl/webglreplay.js @@ -5,9 +5,11 @@ goog.require('goog.array'); goog.require('goog.asserts'); goog.require('goog.object'); goog.require('goog.vec.Mat4'); +goog.require('ol.color.Matrix'); goog.require('ol.extent'); goog.require('ol.render.IReplayGroup'); -goog.require('ol.render.webgl.imagereplay.shader'); +goog.require('ol.render.webgl.imagereplay.shader.Color'); +goog.require('ol.render.webgl.imagereplay.shader.Default'); goog.require('ol.vec.Mat4'); @@ -34,6 +36,12 @@ ol.render.webgl.ImageReplay = function(tolerance, maxExtent) { */ this.anchorY_ = undefined; + /** + * @private + * @type {ol.color.Matrix} + */ + this.colorMatrix_ = new ol.color.Matrix(); + /** * The origin of the coordinate system for the point coordinates sent to * the GPU. To eliminate jitter caused by precision problems in the GPU @@ -50,13 +58,6 @@ ol.render.webgl.ImageReplay = function(tolerance, maxExtent) { */ this.extent_ = ol.extent.createEmpty(); - /** - * @private - * @type {ol.webgl.shader.Fragment} - */ - this.fragmentShader_ = - ol.render.webgl.imagereplay.shader.Fragment.getInstance(); - /** * @type {Array.} * @private @@ -101,9 +102,15 @@ ol.render.webgl.ImageReplay = function(tolerance, maxExtent) { /** * @private - * @type {ol.render.webgl.imagereplay.shader.Locations} + * @type {ol.render.webgl.imagereplay.shader.Color.Locations} */ - this.locations_ = null; + this.colorLocations_ = null; + + /** + * @private + * @type {ol.render.webgl.imagereplay.shader.Default.Locations} + */ + this.defaultLocations_ = null; /** * @private @@ -165,13 +172,6 @@ ol.render.webgl.ImageReplay = function(tolerance, maxExtent) { */ this.textures_ = []; - /** - * @private - * @type {ol.webgl.shader.Vertex} - */ - this.vertexShader_ = - ol.render.webgl.imagereplay.shader.Vertex.getInstance(); - /** * @type {Array.} * @private @@ -502,25 +502,58 @@ ol.render.webgl.ImageReplay.prototype.getExtent = function() { * @param {ol.Extent} extent Extent. * @param {number} pixelRatio Pixel ratio. * @param {number} opacity Global opacity. + * @param {number} brightness Global brightness. + * @param {number} contrast Global contrast. + * @param {number} hue Global hue. + * @param {number} saturation Global saturation. * @param {Object} skippedFeaturesHash Ids of features to skip. * @return {T|undefined} Callback result. * @template T */ ol.render.webgl.ImageReplay.prototype.replay = function(context, center, resolution, rotation, size, extent, pixelRatio, - opacity, skippedFeaturesHash) { + opacity, brightness, contrast, hue, saturation, skippedFeaturesHash) { var gl = context.getGL(); - var program = context.getProgram( - this.fragmentShader_, this.vertexShader_); - context.useProgram(program); + var useColor = brightness || contrast != 1 || hue || saturation != 1; - if (goog.isNull(this.locations_)) { - this.locations_ = - new ol.render.webgl.imagereplay.shader.Locations( - gl, program); + var fragmentShader, vertexShader; + if (useColor) { + fragmentShader = + ol.render.webgl.imagereplay.shader.ColorFragment.getInstance(); + vertexShader = + ol.render.webgl.imagereplay.shader.ColorVertex.getInstance(); + } else { + fragmentShader = + ol.render.webgl.imagereplay.shader.DefaultFragment.getInstance(); + vertexShader = + ol.render.webgl.imagereplay.shader.DefaultVertex.getInstance(); } + var program = context.getProgram(fragmentShader, vertexShader); + + var locations; + if (useColor) { + if (goog.isNull(this.colorLocations_)) { + locations = + new ol.render.webgl.imagereplay.shader.Color.Locations(gl, program); + this.colorLocations_ = locations; + } else { + locations = this.colorLocations_; + } + } else { + if (goog.isNull(this.defaultLocations_)) { + locations = + new ol.render.webgl.imagereplay.shader.Default.Locations(gl, program); + this.defaultLocations_ = locations; + } else { + locations = this.defaultLocations_; + } + } + + // FIXME check return value? + context.useProgram(program); + var projectionMatrix = this.projectionMatrix_; ol.vec.Mat4.makeTransform2D(projectionMatrix, 0.0, 0.0, @@ -538,8 +571,6 @@ ol.render.webgl.ImageReplay.prototype.replay = function(context, goog.vec.Mat4.rotateZ(offsetRotateMatrix, -rotation); } - var locations = this.locations_; - goog.asserts.assert(!goog.isNull(this.verticesBuffer_)); gl.bindBuffer(goog.webgl.ARRAY_BUFFER, this.verticesBuffer_); @@ -568,6 +599,10 @@ ol.render.webgl.ImageReplay.prototype.replay = function(context, gl.uniformMatrix4fv(locations.u_offsetRotateMatrix, false, offsetRotateMatrix); gl.uniform1f(locations.u_opacity, opacity); + if (useColor) { + gl.uniformMatrix4fv(locations.u_colorMatrix, false, + this.colorMatrix_.getMatrix(brightness, contrast, hue, saturation)); + } goog.asserts.assert(!goog.isNull(this.indicesBuffer_)); gl.bindBuffer(goog.webgl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer_); @@ -735,13 +770,17 @@ ol.render.webgl.ReplayGroup.prototype.isEmpty = function() { * @param {ol.Extent} extent Extent. * @param {number} pixelRatio Pixel ratio. * @param {number} opacity Global opacity. + * @param {number} brightness Global brightness. + * @param {number} contrast Global contrast. + * @param {number} hue Global hue. + * @param {number} saturation Global saturation. * @param {Object} skippedFeaturesHash Ids of features to skip. * @return {T|undefined} Callback result. * @template T */ ol.render.webgl.ReplayGroup.prototype.replay = function(context, center, resolution, rotation, size, extent, pixelRatio, - opacity, skippedFeaturesHash) { + opacity, brightness, contrast, hue, saturation, 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]]; @@ -749,7 +788,7 @@ ol.render.webgl.ReplayGroup.prototype.replay = function(context, ol.extent.intersects(extent, replay.getExtent())) { result = replay.replay(context, center, resolution, rotation, size, extent, pixelRatio, - opacity, skippedFeaturesHash); + opacity, brightness, contrast, hue, saturation, skippedFeaturesHash); if (result) { return result; } diff --git a/src/ol/renderer/webgl/webglmaprenderer.js b/src/ol/renderer/webgl/webglmaprenderer.js index 9ec83bf5cd..ab89377a02 100644 --- a/src/ol/renderer/webgl/webglmaprenderer.js +++ b/src/ol/renderer/webgl/webglmaprenderer.js @@ -291,9 +291,14 @@ ol.renderer.webgl.Map.prototype.dispatchComposeEvent_ = var center = viewState.center; var rotation = viewState.rotation; var size = frameState.size; + // use default color values var opacity = 1; + var brightness = 0; + var contrast = 1; + var hue = 0; + var saturation = 1; replayGroup.replay(context, center, resolution, rotation, size, extent, - pixelRatio, opacity, {}); + pixelRatio, opacity, brightness, contrast, hue, saturation, {}); } this.replayGroup = replayGroup; } diff --git a/src/ol/renderer/webgl/webglvectorlayerrenderer.js b/src/ol/renderer/webgl/webglvectorlayerrenderer.js index 773fde46a2..9e1d1546d8 100644 --- a/src/ol/renderer/webgl/webglvectorlayerrenderer.js +++ b/src/ol/renderer/webgl/webglvectorlayerrenderer.js @@ -73,8 +73,8 @@ ol.renderer.webgl.VectorLayer.prototype.composeFrame = replayGroup.replay(context, viewState.center, viewState.resolution, viewState.rotation, frameState.size, frameState.extent, frameState.pixelRatio, - layerState.opacity, - frameState.skippedFeatureUids); + layerState.opacity, layerState.brightness, layerState.contrast, + layerState.hue, layerState.saturation, frameState.skippedFeatureUids); } };