137 lines
3.8 KiB
JavaScript
137 lines
3.8 KiB
JavaScript
WebGLUtil = (function () {
|
|
// ---------------------------------------------------------------------------
|
|
// WebGL helpers
|
|
|
|
function withWebGL2(canvasId, callback, onFinished) {
|
|
var run = function () {
|
|
var canvas = document.getElementById(canvasId);
|
|
|
|
var gl = null;
|
|
try {
|
|
gl = canvas.getContext("webgl2");
|
|
} catch (e) {}
|
|
|
|
if (!gl) {
|
|
todo(false, "WebGL2 is not supported");
|
|
onFinished();
|
|
return;
|
|
}
|
|
|
|
callback(gl);
|
|
onFinished();
|
|
};
|
|
|
|
try {
|
|
var prefArrArr = [
|
|
["webgl.force-enabled", true],
|
|
["webgl.enable-webgl2", true],
|
|
];
|
|
var prefEnv = { set: prefArrArr };
|
|
SpecialPowers.pushPrefEnv(prefEnv, run);
|
|
} catch (e) {
|
|
warning("No SpecialPowers, but trying WebGL2 anyway...");
|
|
run();
|
|
}
|
|
}
|
|
|
|
// Returns a valid shader, or null on errors.
|
|
function createShaderById(gl, id) {
|
|
var elem = document.getElementById(id);
|
|
if (!elem) {
|
|
throw new Error(
|
|
"Failed to create shader from non-existent id '" + id + "'."
|
|
);
|
|
}
|
|
|
|
var src = elem.innerHTML.trim();
|
|
|
|
var shader;
|
|
if (elem.type == "x-shader/x-fragment") {
|
|
shader = gl.createShader(gl.FRAGMENT_SHADER);
|
|
} else if (elem.type == "x-shader/x-vertex") {
|
|
shader = gl.createShader(gl.VERTEX_SHADER);
|
|
} else {
|
|
throw new Error(
|
|
"Bad MIME type for shader '" + id + "': " + elem.type + "."
|
|
);
|
|
}
|
|
|
|
gl.shaderSource(shader, src);
|
|
gl.compileShader(shader);
|
|
|
|
return shader;
|
|
}
|
|
|
|
function createProgramByIds(gl, vsId, fsId) {
|
|
var vs = createShaderById(gl, vsId);
|
|
var fs = createShaderById(gl, fsId);
|
|
if (!vs || !fs) {
|
|
return null;
|
|
}
|
|
|
|
var prog = gl.createProgram();
|
|
gl.attachShader(prog, vs);
|
|
gl.attachShader(prog, fs);
|
|
gl.linkProgram(prog);
|
|
|
|
if (!gl.getProgramParameter(prog, gl.LINK_STATUS)) {
|
|
var str = "Shader program linking failed:";
|
|
str += "\nShader program info log:\n" + gl.getProgramInfoLog(prog);
|
|
str += "\n\nVert shader log:\n" + gl.getShaderInfoLog(vs);
|
|
str += "\n\nFrag shader log:\n" + gl.getShaderInfoLog(fs);
|
|
console.error(str);
|
|
return null;
|
|
}
|
|
|
|
return prog;
|
|
}
|
|
|
|
return {
|
|
withWebGL2,
|
|
|
|
createShaderById,
|
|
createProgramByIds,
|
|
|
|
linkProgramByIds(gl, vertSrcElem, fragSrcElem) {
|
|
const prog = gl.createProgram();
|
|
|
|
function attachShaderById(type, srcElem) {
|
|
const shader = gl.createShader(type);
|
|
gl.shaderSource(shader, srcElem.innerHTML.trim() + "\n");
|
|
gl.compileShader(shader);
|
|
gl.attachShader(prog, shader);
|
|
prog[type] = shader;
|
|
}
|
|
attachShaderById(gl.VERTEX_SHADER, vertSrcElem);
|
|
attachShaderById(gl.FRAGMENT_SHADER, fragSrcElem);
|
|
|
|
gl.linkProgram(prog);
|
|
const success = gl.getProgramParameter(prog, gl.LINK_STATUS);
|
|
if (!success) {
|
|
console.error("Error linking program:");
|
|
console.error("\nLink log: " + gl.getProgramInfoLog(prog));
|
|
console.error(
|
|
"\nVert shader log: " + gl.getShaderInfoLog(prog[gl.VERTEX_SHADER])
|
|
);
|
|
console.error(
|
|
"\nFrag shader log: " + gl.getShaderInfoLog(prog[gl.FRAGMENT_SHADER])
|
|
);
|
|
return null;
|
|
}
|
|
gl.deleteShader(prog[gl.VERTEX_SHADER]);
|
|
gl.deleteShader(prog[gl.FRAGMENT_SHADER]);
|
|
|
|
let count = gl.getProgramParameter(prog, gl.ACTIVE_ATTRIBUTES);
|
|
for (let i = 0; i < count; i++) {
|
|
const info = gl.getActiveAttrib(prog, i);
|
|
prog[info.name] = gl.getAttribLocation(prog, info.name);
|
|
}
|
|
count = gl.getProgramParameter(prog, gl.ACTIVE_UNIFORMS);
|
|
for (let i = 0; i < count; i++) {
|
|
const info = gl.getActiveUniform(prog, i);
|
|
prog[info.name] = gl.getUniformLocation(prog, info.name);
|
|
}
|
|
return prog;
|
|
},
|
|
};
|
|
})();
|