webgl-util.js (3882B)
1 WebGLUtil = (function () { 2 // --------------------------------------------------------------------------- 3 // WebGL helpers 4 5 function withWebGL2(canvasId, callback, onFinished) { 6 var run = function () { 7 var canvas = document.getElementById(canvasId); 8 9 var gl = null; 10 try { 11 gl = canvas.getContext("webgl2"); 12 } catch (e) {} 13 14 if (!gl) { 15 todo(false, "WebGL2 is not supported"); 16 onFinished(); 17 return; 18 } 19 20 callback(gl); 21 onFinished(); 22 }; 23 24 try { 25 var prefArrArr = [ 26 ["webgl.force-enabled", true], 27 ["webgl.enable-webgl2", true], 28 ]; 29 var prefEnv = { set: prefArrArr }; 30 SpecialPowers.pushPrefEnv(prefEnv, run); 31 } catch (e) { 32 warning("No SpecialPowers, but trying WebGL2 anyway..."); 33 run(); 34 } 35 } 36 37 // Returns a valid shader, or null on errors. 38 function createShaderById(gl, id) { 39 var elem = document.getElementById(id); 40 if (!elem) { 41 throw new Error( 42 "Failed to create shader from non-existent id '" + id + "'." 43 ); 44 } 45 46 var src = elem.innerHTML.trim(); 47 48 var shader; 49 if (elem.type == "x-shader/x-fragment") { 50 shader = gl.createShader(gl.FRAGMENT_SHADER); 51 } else if (elem.type == "x-shader/x-vertex") { 52 shader = gl.createShader(gl.VERTEX_SHADER); 53 } else { 54 throw new Error( 55 "Bad MIME type for shader '" + id + "': " + elem.type + "." 56 ); 57 } 58 59 gl.shaderSource(shader, src); 60 gl.compileShader(shader); 61 62 return shader; 63 } 64 65 function createProgramByIds(gl, vsId, fsId) { 66 var vs = createShaderById(gl, vsId); 67 var fs = createShaderById(gl, fsId); 68 if (!vs || !fs) { 69 return null; 70 } 71 72 var prog = gl.createProgram(); 73 gl.attachShader(prog, vs); 74 gl.attachShader(prog, fs); 75 gl.linkProgram(prog); 76 77 if (!gl.getProgramParameter(prog, gl.LINK_STATUS)) { 78 var str = "Shader program linking failed:"; 79 str += "\nShader program info log:\n" + gl.getProgramInfoLog(prog); 80 str += "\n\nVert shader log:\n" + gl.getShaderInfoLog(vs); 81 str += "\n\nFrag shader log:\n" + gl.getShaderInfoLog(fs); 82 console.error(str); 83 return null; 84 } 85 86 return prog; 87 } 88 89 return { 90 withWebGL2, 91 92 createShaderById, 93 createProgramByIds, 94 95 linkProgramByIds(gl, vertSrcElem, fragSrcElem) { 96 const prog = gl.createProgram(); 97 98 function attachShaderById(type, srcElem) { 99 const shader = gl.createShader(type); 100 gl.shaderSource(shader, srcElem.innerHTML.trim() + "\n"); 101 gl.compileShader(shader); 102 gl.attachShader(prog, shader); 103 prog[type] = shader; 104 } 105 attachShaderById(gl.VERTEX_SHADER, vertSrcElem); 106 attachShaderById(gl.FRAGMENT_SHADER, fragSrcElem); 107 108 gl.linkProgram(prog); 109 const success = gl.getProgramParameter(prog, gl.LINK_STATUS); 110 if (!success) { 111 console.error("Error linking program:"); 112 console.error("\nLink log: " + gl.getProgramInfoLog(prog)); 113 console.error( 114 "\nVert shader log: " + gl.getShaderInfoLog(prog[gl.VERTEX_SHADER]) 115 ); 116 console.error( 117 "\nFrag shader log: " + gl.getShaderInfoLog(prog[gl.FRAGMENT_SHADER]) 118 ); 119 return null; 120 } 121 gl.deleteShader(prog[gl.VERTEX_SHADER]); 122 gl.deleteShader(prog[gl.FRAGMENT_SHADER]); 123 124 let count = gl.getProgramParameter(prog, gl.ACTIVE_ATTRIBUTES); 125 for (let i = 0; i < count; i++) { 126 const info = gl.getActiveAttrib(prog, i); 127 prog[info.name] = gl.getAttribLocation(prog, info.name); 128 } 129 count = gl.getProgramParameter(prog, gl.ACTIVE_UNIFORMS); 130 for (let i = 0; i < count; i++) { 131 const info = gl.getActiveUniform(prog, i); 132 prog[info.name] = gl.getUniformLocation(prog, info.name); 133 } 134 return prog; 135 }, 136 }; 137 })();