mapbox-gl
Version:
A WebGL interactive maps library
96 lines (76 loc) • 3.44 kB
JavaScript
;
var assert = require('assert');
var util = require('../../util/util');
var shaders = require('mapbox-gl-shaders');
var utilSource = shaders.util;
module.exports._createProgram = function(name, defines, vertexPragmas, fragmentPragmas) {
var gl = this.gl;
var program = gl.createProgram();
var definition = shaders[name];
var definesSource = '#define MAPBOX_GL_JS;\n';
for (var j = 0; j < defines.length; j++) {
definesSource += '#define ' + defines[j] + ';\n';
}
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, applyPragmas(definesSource + definition.fragmentSource, fragmentPragmas));
gl.compileShader(fragmentShader);
assert(gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS), gl.getShaderInfoLog(fragmentShader));
gl.attachShader(program, fragmentShader);
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, applyPragmas(definesSource + utilSource + definition.vertexSource, vertexPragmas));
gl.compileShader(vertexShader);
assert(gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS), gl.getShaderInfoLog(vertexShader));
gl.attachShader(program, vertexShader);
gl.linkProgram(program);
assert(gl.getProgramParameter(program, gl.LINK_STATUS), gl.getProgramInfoLog(program));
var attributes = {};
var numAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
for (var i = 0; i < numAttributes; i++) {
var attribute = gl.getActiveAttrib(program, i);
attributes[attribute.name] = gl.getAttribLocation(program, attribute.name);
}
var uniforms = {};
var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
for (var ui = 0; ui < numUniforms; ui++) {
var uniform = gl.getActiveUniform(program, ui);
uniforms[uniform.name] = gl.getUniformLocation(program, uniform.name);
}
return util.extend({
program: program,
definition: definition,
attributes: attributes,
numAttributes: numAttributes
}, attributes, uniforms);
};
module.exports._createProgramCached = function(name, defines, vertexPragmas, fragmentPragmas) {
this.cache = this.cache || {};
var key = JSON.stringify({
name: name,
defines: defines,
vertexPragmas: vertexPragmas,
fragmentPragmas: fragmentPragmas
});
if (!this.cache[key]) {
this.cache[key] = this._createProgram(name, defines, vertexPragmas, fragmentPragmas);
}
return this.cache[key];
};
module.exports.useProgram = function (nextProgramName, defines, vertexPragmas, fragmentPragmas) {
var gl = this.gl;
defines = defines || [];
if (this._showOverdrawInspector) {
defines = defines.concat('OVERDRAW_INSPECTOR');
}
var nextProgram = this._createProgramCached(nextProgramName, defines, vertexPragmas, fragmentPragmas);
var previousProgram = this.currentProgram;
if (previousProgram !== nextProgram) {
gl.useProgram(nextProgram.program);
this.currentProgram = nextProgram;
}
return nextProgram;
};
function applyPragmas(source, pragmas) {
return source.replace(/#pragma mapbox: ([\w]+) ([\w]+) ([\w]+) ([\w]+)/g, function(match, operation, precision, type, name) {
return pragmas[operation][name].replace(/{type}/g, type).replace(/{precision}/g, precision);
});
}