mapbox-gl
Version:
A WebGL interactive maps library
128 lines (105 loc) • 4.83 kB
JavaScript
'use strict';
var shaders = require('./shaders');
var util = require('../util/util');
exports.extend = function(context) {
var origLineWidth = context.lineWidth,
lineWidthRange = context.getParameter(context.ALIASED_LINE_WIDTH_RANGE);
context.lineWidth = function(width) {
origLineWidth.call(context, util.clamp(width, lineWidthRange[0], lineWidthRange[1]));
};
context.getShader = function(name, type) {
var kind = type === this.FRAGMENT_SHADER ? 'fragment' : 'vertex';
if (!shaders[name] || !shaders[name][kind]) {
throw new Error("Could not find shader " + name);
}
var shader = this.createShader(type);
var shaderSource = shaders[name][kind];
if (typeof orientation === 'undefined') {
// only use highp precision on mobile browsers
shaderSource = shaderSource.replace(/ highp /g, ' ');
}
this.shaderSource(shader, shaderSource);
this.compileShader(shader);
if (!this.getShaderParameter(shader, this.COMPILE_STATUS)) {
throw new Error(this.getShaderInfoLog(shader));
}
return shader;
};
context.initializeShader = function(name, attributes, uniforms) {
var shader = {
program: this.createProgram(),
fragment: this.getShader(name, this.FRAGMENT_SHADER),
vertex: this.getShader(name, this.VERTEX_SHADER),
attributes: []
};
this.attachShader(shader.program, shader.vertex);
this.attachShader(shader.program, shader.fragment);
this.linkProgram(shader.program);
if (!this.getProgramParameter(shader.program, this.LINK_STATUS)) {
console.error(this.getProgramInfoLog(shader.program));
} else {
for (var i = 0; i < attributes.length; i++) {
shader[attributes[i]] = this.getAttribLocation(shader.program, attributes[i]);
shader.attributes.push(shader[attributes[i]]);
}
for (var k = 0; k < uniforms.length; k++) {
shader[uniforms[k]] = this.getUniformLocation(shader.program, uniforms[k]);
}
}
return shader;
};
// Switches to a different shader program.
context.switchShader = function(shader, posMatrix, exMatrix) {
if (this.currentShader !== shader) {
this.useProgram(shader.program);
// Disable all attributes from the existing shader that aren't used in
// the new shader. Note: attribute indices are *not* program specific!
var enabled = this.currentShader ? this.currentShader.attributes : [];
var required = shader.attributes;
for (var i = 0; i < enabled.length; i++) {
if (required.indexOf(enabled[i]) < 0) {
this.disableVertexAttribArray(enabled[i]);
}
}
// Enable all attributes for the new shader.
for (var j = 0; j < required.length; j++) {
if (enabled.indexOf(required[j]) < 0) {
this.enableVertexAttribArray(required[j]);
}
}
this.currentShader = shader;
}
if (posMatrix !== undefined) context.setPosMatrix(posMatrix);
if (exMatrix !== undefined) context.setExMatrix(exMatrix);
};
// Update the matrices if necessary. Note: This relies on object identity!
// This means changing the matrix values without the actual matrix object
// will FAIL to update the matrix properly.
context.setPosMatrix = function(posMatrix) {
var shader = this.currentShader;
if (shader.posMatrix !== posMatrix) {
this.uniformMatrix4fv(shader.u_matrix, false, posMatrix);
shader.posMatrix = posMatrix;
}
};
// Update the matrices if necessary. Note: This relies on object identity!
// This means changing the matrix values without the actual matrix object
// will FAIL to update the matrix properly.
context.setExMatrix = function(exMatrix) {
var shader = this.currentShader;
if (exMatrix && shader.exMatrix !== exMatrix && shader.u_exmatrix) {
this.uniformMatrix4fv(shader.u_exmatrix, false, exMatrix);
shader.exMatrix = exMatrix;
}
};
context.vertexAttrib2fv = function(attribute, values) {
context.vertexAttrib2f(attribute, values[0], values[1]);
};
context.vertexAttrib3fv = function(attribute, values) {
context.vertexAttrib3f(attribute, values[0], values[1], values[2]);
};
context.vertexAttrib4fv = function(attribute, values) {
context.vertexAttrib4f(attribute, values[0], values[1], values[2], values[3]);
};
return context;
};