Refactor shader and program management
This commit is contained in:
@@ -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.<number, WebGLShader>}
|
||||
*/
|
||||
this.shaderCache_ = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, WebGLProgram>}
|
||||
*/
|
||||
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_ = {};
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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_);
|
||||
};
|
||||
@@ -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.<string, Object.<string, ol.webgl.Program>>}
|
||||
*/
|
||||
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);
|
||||
};
|
||||
@@ -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.<ol.webgl.Uniform>=} 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.<ol.webgl.Uniform>}
|
||||
*/
|
||||
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;
|
||||
|
||||
@@ -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.<ol.webgl.Uniform>=} 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;
|
||||
};
|
||||
|
||||
@@ -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.<ol.webgl.Uniform>=} 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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user