diff --git a/src/ol/webgl/map.js b/src/ol/webgl/map.js index 13fac630d6..0fb3c9c195 100644 --- a/src/ol/webgl/map.js +++ b/src/ol/webgl/map.js @@ -8,7 +8,10 @@ goog.require('goog.webgl'); goog.require('ol.Layer'); goog.require('ol.Map'); goog.require('ol.TileLayer'); +goog.require('ol.webgl.Shader'); goog.require('ol.webgl.TileLayerRenderer'); +goog.require('ol.webgl.shader.Fragment'); +goog.require('ol.webgl.shader.Vertex'); /** @@ -59,6 +62,30 @@ ol.webgl.Map = function(target, opt_values) { goog.events.listen(this.canvas_, ol.webgl.WebGLContextEventType.RESTORED, this.handleWebGLContextRestored, false, this); + /** + * @private + * @type {Object.} + */ + this.shaderCache_ = {}; + + /** + * @private + * @type {Object.} + */ + this.programCache_ = {}; + + /** + * @private + * @type {ol.webgl.shader.Fragment} + */ + this.fragmentShader_ = ol.webgl.Map.createFragmentShader_(); + + /** + * @private + * @type {ol.webgl.shader.Vertex} + */ + this.vertexShader_ = ol.webgl.Map.createVertexShader_(); + if (goog.isDef(opt_values)) { this.setValues(opt_values); } @@ -70,6 +97,45 @@ ol.webgl.Map = function(target, opt_values) { goog.inherits(ol.webgl.Map, ol.Map); +/** + * @private + * @return {ol.webgl.shader.Fragment} Fragment shader. + */ +ol.webgl.Map.createFragmentShader_ = function() { + return new ol.webgl.shader.Fragment([ + 'precision mediump float;', + '', + 'uniform float uAlpha;', + 'uniform sampler2D uTexture;', + '', + 'varying vec2 vTexCoord;', + '', + 'void main(void) {', + ' gl_FragColor = vec4(texture2D(uTexture, vTexCoord).rgb, uAlpha);', + '}' + ].join('\n')); +}; + + +/** + * @private + * @return {ol.webgl.shader.Vertex} Vertex shader. + */ +ol.webgl.Map.createVertexShader_ = function() { + return new ol.webgl.shader.Vertex([ + 'attribute vec2 aPosition;', + 'attribute vec2 aTexCoord;', + '', + 'varying vec2 vTexCoord;', + '', + 'void main(void) {', + ' gl_Position = vec4(aPosition, 0., 1.);', + ' vTexCoord = aTexCoord;', + '}' + ].join('\n')); +}; + + /** * @inheritDoc */ @@ -87,6 +153,23 @@ ol.webgl.Map.prototype.createLayerRenderer = function(layer) { }; +/** + * @inheritDoc + */ +ol.webgl.Map.prototype.disposeInternal = function() { + var gl = this.getGL(); + if (!gl.isContextLost()) { + goog.object.forEach(this.programCache_, function(program) { + gl.deleteProgram(program); + }); + goog.object.forEach(this.shaderCache_, function(shader) { + gl.deleteShader(shader); + }); + } + goog.base(this, 'disposeInternal'); +}; + + /** * @return {WebGLRenderingContext} GL. */ @@ -95,6 +178,60 @@ ol.webgl.Map.prototype.getGL = function() { }; +/** + * @param {ol.webgl.shader.Fragment} fragmentShaderObject Fragment shader. + * @param {ol.webgl.shader.Vertex} vertexShaderObject Vertex shader. + * @return {WebGLProgram} Program. + */ +ol.webgl.Map.prototype.getProgram = function( + fragmentShaderObject, vertexShaderObject) { + var key = + goog.getUid(fragmentShaderObject) + '/' + goog.getUid(vertexShaderObject); + if (key in this.programCache_) { + return this.programCache_[key]; + } else { + var gl = this.getGL(); + var program = gl.createProgram(); + gl.attachShader(program, this.getShader(fragmentShaderObject)); + gl.attachShader(program, this.getShader(vertexShaderObject)); + gl.linkProgram(program); + if (!gl.getProgramParameter(program, goog.webgl.LINK_STATUS) && + !gl.isContextLost()) { + window.console.log(gl.getProgramInfoLog(program)); + goog.asserts.assert( + gl.getProgramParameter(program, goog.webgl.LINK_STATUS)); + } + this.programCache_[key] = program; + return program; + } +}; + + +/** + * @param {ol.webgl.Shader} shaderObject Shader object. + * @return {WebGLShader} Shader. + */ +ol.webgl.Map.prototype.getShader = function(shaderObject) { + var key = goog.getUid(shaderObject); + if (key in this.shaderCache_) { + return this.shaderCache_[key]; + } else { + var gl = this.getGL(); + var shader = gl.createShader(shaderObject.getType()); + gl.shaderSource(shader, shaderObject.getSource()); + gl.compileShader(shader); + if (!gl.getShaderParameter(shader, goog.webgl.COMPILE_STATUS) && + !gl.isContextLost()) { + window.console.log(gl.getShaderInfoLog(shader)); + goog.asserts.assert( + gl.getShaderParameter(shader, goog.webgl.COMPILE_STATUS)); + } + this.shaderCache_[key] = shader; + return shader; + } +}; + + /** * @inheritDoc */ @@ -165,6 +302,8 @@ ol.webgl.Map.prototype.handleWebGLContextLost = function(event) { goog.dispose(layerRenderer); }, this); goog.asserts.assert(goog.object.isEmpty(this.layerRenderers)); + this.shaderCache_ = {}; + this.programCache_ = {}; }; diff --git a/src/ol/webgl/program.js b/src/ol/webgl/program.js deleted file mode 100644 index 39f75ab037..0000000000 --- a/src/ol/webgl/program.js +++ /dev/null @@ -1,79 +0,0 @@ -goog.provide('ol.webgl.Program'); - -goog.require('goog.asserts'); -goog.require('goog.webgl'); -goog.require('ol.webgl.GLObject'); -goog.require('ol.webgl.VertexAttrib'); -goog.require('ol.webgl.shader.Fragment'); -goog.require('ol.webgl.shader.Vertex'); - - - -/** - * @constructor - * @extends {ol.webgl.GLObject} - * @param {ol.webgl.shader.Fragment} fragmentShader Fragment shader. - * @param {ol.webgl.shader.Vertex} vertexShader Vertex shader. - */ -ol.webgl.Program = function(fragmentShader, vertexShader) { - - goog.base(this); - - /** - * @private - * @type {ol.webgl.shader.Fragment} - */ - this.fragmentShader_ = fragmentShader; - - /** - * @private - * @type {ol.webgl.shader.Vertex} - */ - this.vertexShader_ = vertexShader; - - /** - * @private - * @type {WebGLProgram} - */ - this.program_ = null; - -}; -goog.inherits(ol.webgl.Program, ol.webgl.GLObject); - - -/** - * @inheritDoc - */ -ol.webgl.Program.prototype.setGL = function(gl) { - if (!goog.isNull(this.gl)) { - if (!goog.isNull(this.program_)) { - this.gl.deleteProgram(this.program_); - this.program_ = null; - } - this.fragmentShader_.setGL(null); - this.vertexShader_.setGL(null); - } - goog.base(this, 'setGL', gl); - if (!goog.isNull(gl)) { - this.fragmentShader_.setGL(gl); - this.vertexShader_.setGL(gl); - var program = gl.createProgram(); - gl.attachShader(program, this.fragmentShader_.get()); - gl.attachShader(program, this.vertexShader_.get()); - gl.linkProgram(program); - if (!gl.getProgramParameter(program, goog.webgl.LINK_STATUS)) { - window.console.log(gl.getProgramInfoLog(program)); - goog.asserts.assert( - gl.getProgramParameter(program, goog.webgl.LINK_STATUS)); - } - this.program_ = program; - } -}; - - -/** - */ -ol.webgl.Program.prototype.use = function() { - var gl = this.getGL(); - gl.useProgram(this.program_); -}; diff --git a/src/ol/webgl/programcache.js b/src/ol/webgl/programcache.js deleted file mode 100644 index 9e08deb9d8..0000000000 --- a/src/ol/webgl/programcache.js +++ /dev/null @@ -1,64 +0,0 @@ -goog.provide('ol.webgl.ProgramCache'); - -goog.require('goog.dispose'); -goog.require('goog.object'); -goog.require('ol.webgl.GLObject'); -goog.require('ol.webgl.Program'); -goog.require('ol.webgl.shader.Fragment'); -goog.require('ol.webgl.shader.Vertex'); - - - -/** - * @constructor - * @extends {ol.webgl.GLObject} - */ -ol.webgl.ProgramCache = function() { - - goog.base(this); - - /** - * @private - * @type {Object.>} - */ - this.programss_ = {}; - -}; -goog.inherits(ol.webgl.ProgramCache, ol.webgl.GLObject); - - -/** - * @param {ol.webgl.shader.Fragment} fragmentShader Fragment shader. - * @param {ol.webgl.shader.Vertex} vertexShader Vertex shader. - * @return {ol.webgl.Program} Program. - */ -ol.webgl.ProgramCache.prototype.get = - function(fragmentShader, vertexShader) { - var program, programs; - var fragmentShaderKey = goog.getUid(fragmentShader); - if (fragmentShaderKey in this.programss_) { - programs = this.programss_[fragmentShaderKey]; - } else { - programs = {}; - this.programss_[fragmentShaderKey] = programs; - } - var vertexShaderKey = goog.getUid(vertexShader); - if (vertexShaderKey in programs) { - program = programs[vertexShaderKey]; - } else { - program = new ol.webgl.Program(fragmentShader, vertexShader); - programs[vertexShaderKey] = program; - } - return program; -}; - - -/** - * @inheritDoc - */ -ol.webgl.ProgramCache.prototype.setGL = function(gl) { - goog.object.forEach(this.programss_, function(programs) { - goog.disposeAll(goog.object.getValues(programs)); - }); - goog.base(this, 'setGL', gl); -}; diff --git a/src/ol/webgl/shader.js b/src/ol/webgl/shader.js index 8d3ceb4031..9edc305533 100644 --- a/src/ol/webgl/shader.js +++ b/src/ol/webgl/shader.js @@ -1,28 +1,14 @@ goog.provide('ol.webgl.Shader'); -goog.require('goog.array'); -goog.require('goog.asserts'); -goog.require('goog.webgl'); -goog.require('ol.webgl.GLObject'); -goog.require('ol.webgl.Uniform'); +goog.require('goog.functions'); /** * @constructor - * @extends {ol.webgl.GLObject} * @param {string} source Source. - * @param {Array.=} opt_uniforms Uniforms. */ -ol.webgl.Shader = function(source, opt_uniforms) { - - goog.base(this); - - /** - * @private - * @type {WebGLShader} - */ - this.shader_ = null; +ol.webgl.Shader = function(source) { /** * @private @@ -30,88 +16,24 @@ ol.webgl.Shader = function(source, opt_uniforms) { */ this.source_ = source; - /** - * @private - * @type {Array.} - */ - this.uniforms_ = opt_uniforms || []; - -}; -goog.inherits(ol.webgl.Shader, ol.webgl.GLObject); - - -/** - */ -ol.webgl.Shader.prototype.compile = function() { - var gl = this.getGL(); - this.shader_ = this.create(); - gl.shaderSource(this.shader_, this.source_); - gl.compileShader(this.shader_); - if (!gl.getShaderParameter(this.shader_, goog.webgl.COMPILE_STATUS)) { - window.console.log(gl.getShaderInfoLog(this.shader_)); - goog.asserts.assert( - gl.getShaderParameter(this.shader_, goog.webgl.COMPILE_STATUS)); - } }; /** - * @protected - * @return {WebGLShader} Shader. + * @return {number} Type. */ -ol.webgl.Shader.prototype.create = goog.abstractMethod; +ol.webgl.Shader.prototype.getType = goog.abstractMethod; /** - * @return {WebGLShader} Shader. + * @return {string} Source. */ -ol.webgl.Shader.prototype.get = function() { - return this.shader_; +ol.webgl.Shader.prototype.getSource = function() { + return this.source_; }; /** * @return {boolean} Is animated? */ -ol.webgl.Shader.prototype.isAnimated = function() { - return false; -}; - - -/** - * @inheritDoc - */ -ol.webgl.Shader.prototype.setGL = function(gl) { - if (!goog.isNull(this.gl)) { - goog.array.forEach(this.uniforms_, function(uniform) { - uniform.setGL(null); - }); - if (!goog.isNull(this.shader_)) { - this.gl.deleteShader(this.shader_); - this.shader_ = null; - } - } - goog.base(this, 'setGL', gl); - if (!goog.isNull(gl)) { - this.compile(); - goog.array.forEach(this.uniforms_, function(uniform) { - uniform.setGL(gl); - }); - } -}; - - -/** - * @param {WebGLProgram} program Program. - */ -ol.webgl.Shader.prototype.setProgram = function(program) { - goog.array.forEach(this.uniforms_, function(uniform) { - uniform.setProgram(program); - }); -}; - - -/** - */ -ol.webgl.Shader.prototype.setUniforms = function() { -}; +ol.webgl.Shader.prototype.isAnimated = goog.functions.FALSE; diff --git a/src/ol/webgl/shader/fragment.js b/src/ol/webgl/shader/fragment.js index fb3cd2c6cb..dd6c0ed758 100644 --- a/src/ol/webgl/shader/fragment.js +++ b/src/ol/webgl/shader/fragment.js @@ -1,5 +1,6 @@ goog.provide('ol.webgl.shader.Fragment'); +goog.require('goog.webgl'); goog.require('ol.webgl.Shader'); @@ -8,19 +9,16 @@ goog.require('ol.webgl.Shader'); * @constructor * @extends {ol.webgl.Shader} * @param {string} source Source. - * @param {Array.=} opt_uniforms Uniforms. */ -ol.webgl.shader.Fragment = function(source, opt_uniforms) { - goog.base(this, source, opt_uniforms); +ol.webgl.shader.Fragment = function(source) { + goog.base(this, source); }; goog.inherits(ol.webgl.shader.Fragment, ol.webgl.Shader); /** - * @protected - * @return {WebGLShader} Shader. + * @inheritDoc */ -ol.webgl.shader.Fragment.prototype.create = function() { - var gl = this.getGL(); - return gl.createShader(gl.FRAGMENT_SHADER); +ol.webgl.shader.Fragment.prototype.getType = function() { + return goog.webgl.FRAGMENT_SHADER; }; diff --git a/src/ol/webgl/shader/vertex.js b/src/ol/webgl/shader/vertex.js index a2d58592ea..c1cacbe595 100644 --- a/src/ol/webgl/shader/vertex.js +++ b/src/ol/webgl/shader/vertex.js @@ -1,5 +1,6 @@ goog.provide('ol.webgl.shader.Vertex'); +goog.require('goog.webgl'); goog.require('ol.webgl.Shader'); @@ -8,19 +9,16 @@ goog.require('ol.webgl.Shader'); * @constructor * @extends {ol.webgl.Shader} * @param {string} source Source. - * @param {Array.=} opt_uniforms Uniforms. */ -ol.webgl.shader.Vertex = function(source, opt_uniforms) { - goog.base(this, source, opt_uniforms); +ol.webgl.shader.Vertex = function(source) { + goog.base(this, source); }; goog.inherits(ol.webgl.shader.Vertex, ol.webgl.Shader); /** - * @protected - * @return {WebGLShader} Shader. + * @inheritDoc */ -ol.webgl.shader.Vertex.prototype.create = function() { - var gl = this.getGL(); - return gl.createShader(gl.VERTEX_SHADER); +ol.webgl.shader.Vertex.prototype.getType = function() { + return goog.webgl.VERTEX_SHADER; }; diff --git a/src/ol/webgl/texture.js b/src/ol/webgl/texture.js index cf8a792ede..6f62f2f78e 100644 --- a/src/ol/webgl/texture.js +++ b/src/ol/webgl/texture.js @@ -8,9 +8,8 @@ goog.require('ol.webgl.GLObject'); /** * @constructor * @extends {ol.webgl.GLObject} - * @param {Image} image Image. */ -ol.webgl.Texture = function(image) { +ol.webgl.Texture = function() { goog.base(this);