Index: third_party/webgl/conformance-suites/1.0.0/conformance/more/util.js |
=================================================================== |
--- third_party/webgl/conformance-suites/1.0.0/conformance/more/util.js (revision 121077) |
+++ third_party/webgl/conformance-suites/1.0.0/conformance/more/util.js (working copy) |
@@ -1,1248 +0,0 @@ |
-/* |
-Utilities for the OpenGL ES 2.0 HTML Canvas context |
- |
-Copyright (C) 2009 Ilmari Heikkinen <ilmari.heikkinen@gmail.com> |
- |
-Permission is hereby granted, free of charge, to any person |
-obtaining a copy of this software and associated documentation |
-files (the "Software"), to deal in the Software without |
-restriction, including without limitation the rights to use, |
-copy, modify, merge, publish, distribute, sublicense, and/or sell |
-copies of the Software, and to permit persons to whom the |
-Software is furnished to do so, subject to the following |
-conditions: |
- |
-The above copyright notice and this permission notice shall be |
-included in all copies or substantial portions of the Software. |
- |
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
-OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
-HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
-OTHER DEALINGS IN THE SOFTWARE. |
-*/ |
- |
-function loadTexture(gl, elem, mipmaps) { |
- var tex = gl.createTexture(); |
- gl.bindTexture(gl.TEXTURE_2D, tex); |
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, elem); |
- if (mipmaps != false) |
- gl.generateMipmap(gl.TEXTURE_2D); |
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); |
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); |
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); |
- if (mipmaps) |
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); |
- else |
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); |
- return tex; |
-} |
- |
-function getShader(gl, id) { |
- var shaderScript = document.getElementById(id); |
- if (!shaderScript) { |
- throw(new Error("No shader element with id: "+id)); |
- } |
- |
- var str = ""; |
- var k = shaderScript.firstChild; |
- while (k) { |
- if (k.nodeType == 3) |
- str += k.textContent; |
- k = k.nextSibling; |
- } |
- |
- var shader; |
- if (shaderScript.type == "x-shader/x-fragment") { |
- shader = gl.createShader(gl.FRAGMENT_SHADER); |
- } else if (shaderScript.type == "x-shader/x-vertex") { |
- shader = gl.createShader(gl.VERTEX_SHADER); |
- } else { |
- throw(new Error("Unknown shader type "+shaderScript.type)); |
- } |
- |
- gl.shaderSource(shader, str); |
- gl.compileShader(shader); |
- |
- if (gl.getShaderParameter(shader, gl.COMPILE_STATUS) != 1) { |
- var ilog = gl.getShaderInfoLog(shader); |
- gl.deleteShader(shader); |
- throw(new Error("Failed to compile shader "+shaderScript.id + ", Shader info log: " + ilog)); |
- } |
- return shader; |
-} |
- |
-function loadShaderArray(gl, shaders) { |
- var id = gl.createProgram(); |
- var shaderObjs = []; |
- for (var i=0; i<shaders.length; ++i) { |
- try { |
- var sh = getShader(gl, shaders[i]); |
- shaderObjs.push(sh); |
- gl.attachShader(id, sh); |
- } catch (e) { |
- var pr = {program: id, shaders: shaderObjs}; |
- deleteShader(gl, pr); |
- throw (e); |
- } |
- } |
- var prog = {program: id, shaders: shaderObjs}; |
- gl.linkProgram(id); |
- gl.validateProgram(id); |
- if (gl.getProgramParameter(id, gl.LINK_STATUS) != 1) { |
- deleteShader(gl,prog); |
- throw(new Error("Failed to link shader")); |
- } |
- if (gl.getProgramParameter(id, gl.VALIDATE_STATUS) != 1) { |
- deleteShader(gl,prog); |
- throw(new Error("Failed to validate shader")); |
- } |
- return prog; |
-} |
-function loadShader(gl) { |
- var sh = []; |
- for (var i=1; i<arguments.length; ++i) |
- sh.push(arguments[i]); |
- return loadShaderArray(gl, sh); |
-} |
- |
-function deleteShader(gl, sh) { |
- gl.useProgram(null); |
- sh.shaders.forEach(function(s){ |
- gl.detachShader(sh.program, s); |
- gl.deleteShader(s); |
- }); |
- gl.deleteProgram(sh.program); |
-} |
- |
-function getGLErrorAsString(ctx, err) { |
- if (err === ctx.NO_ERROR) { |
- return "NO_ERROR"; |
- } |
- for (var name in ctx) { |
- if (ctx[name] === err) { |
- return name; |
- } |
- } |
- return err.toString(); |
-} |
- |
-function checkError(gl, msg) { |
- var e = gl.getError(); |
- if (e != gl.NO_ERROR) { |
- log("Error " + getGLErrorAsString(gl, e) + " at " + msg); |
- } |
- return e; |
-} |
- |
-function throwError(gl, msg) { |
- var e = gl.getError(); |
- if (e != 0) { |
- throw(new Error("Error " + getGLErrorAsString(gl, e) + " at " + msg)); |
- } |
-} |
- |
-Math.cot = function(z) { return 1.0 / Math.tan(z); } |
- |
-/* |
- Matrix utilities, using the OpenGL element order where |
- the last 4 elements are the translation column. |
- |
- Uses flat arrays as matrices for performance. |
- |
- Most operations have in-place variants to avoid allocating temporary matrices. |
- |
- Naming logic: |
- Matrix.method operates on a 4x4 Matrix and returns a new Matrix. |
- Matrix.method3x3 operates on a 3x3 Matrix and returns a new Matrix. Not all operations have a 3x3 version (as 3x3 is usually only used for the normal matrix: Matrix.transpose3x3(Matrix.inverseTo3x3(mat4x4))) |
- Matrix.method[3x3]InPlace(args, target) stores its result in the target matrix. |
- |
- Matrix.scale([sx, sy, sz]) -- non-uniform scale by vector |
- Matrix.scale1(s) -- uniform scale by scalar |
- Matrix.scale3(sx, sy, sz) -- non-uniform scale by scalars |
- |
- Ditto for translate. |
-*/ |
-Matrix = { |
- identity : [ |
- 1.0, 0.0, 0.0, 0.0, |
- 0.0, 1.0, 0.0, 0.0, |
- 0.0, 0.0, 1.0, 0.0, |
- 0.0, 0.0, 0.0, 1.0 |
- ], |
- |
- newIdentity : function() { |
- return [ |
- 1.0, 0.0, 0.0, 0.0, |
- 0.0, 1.0, 0.0, 0.0, |
- 0.0, 0.0, 1.0, 0.0, |
- 0.0, 0.0, 0.0, 1.0 |
- ]; |
- }, |
- |
- newIdentity3x3 : function() { |
- return [ |
- 1.0, 0.0, 0.0, |
- 0.0, 1.0, 0.0, |
- 0.0, 0.0, 1.0 |
- ]; |
- }, |
- |
- copyMatrix : function(src, dst) { |
- for (var i=0; i<16; i++) dst[i] = src[i]; |
- return dst; |
- }, |
- |
- to3x3 : function(m) { |
- return [ |
- m[0], m[1], m[2], |
- m[4], m[5], m[6], |
- m[8], m[9], m[10] |
- ]; |
- }, |
- |
- // orthonormal matrix inverse |
- inverseON : function(m) { |
- var n = this.transpose4x4(m); |
- var t = [m[12], m[13], m[14]]; |
- n[3] = n[7] = n[11] = 0; |
- n[12] = -Vec3.dot([n[0], n[4], n[8]], t); |
- n[13] = -Vec3.dot([n[1], n[5], n[9]], t); |
- n[14] = -Vec3.dot([n[2], n[6], n[10]], t); |
- return n; |
- }, |
- |
- inverseTo3x3 : function(m) { |
- return this.inverse4x4to3x3InPlace(m, this.newIdentity3x3()); |
- }, |
- |
- inverseTo3x3InPlace : function(m,n) { |
- var a11 = m[10]*m[5]-m[6]*m[9], |
- a21 = -m[10]*m[1]+m[2]*m[9], |
- a31 = m[6]*m[1]-m[2]*m[5], |
- a12 = -m[10]*m[4]+m[6]*m[8], |
- a22 = m[10]*m[0]-m[2]*m[8], |
- a32 = -m[6]*m[0]+m[2]*m[4], |
- a13 = m[9]*m[4]-m[5]*m[8], |
- a23 = -m[9]*m[0]+m[1]*m[8], |
- a33 = m[5]*m[0]-m[1]*m[4]; |
- var det = m[0]*(a11) + m[1]*(a12) + m[2]*(a13); |
- if (det == 0) // no inverse |
- return [1,0,0,0,1,0,0,0,1]; |
- var idet = 1 / det; |
- n[0] = idet*a11; |
- n[1] = idet*a21; |
- n[2] = idet*a31; |
- n[3] = idet*a12; |
- n[4] = idet*a22; |
- n[5] = idet*a32; |
- n[6] = idet*a13; |
- n[7] = idet*a23; |
- n[8] = idet*a33; |
- return n; |
- }, |
- |
- inverse3x3 : function(m) { |
- return this.inverse3x3InPlace(m, this.newIdentity3x3()); |
- }, |
- |
- inverse3x3InPlace : function(m,n) { |
- var a11 = m[8]*m[4]-m[5]*m[7], |
- a21 = -m[8]*m[1]+m[2]*m[7], |
- a31 = m[5]*m[1]-m[2]*m[4], |
- a12 = -m[8]*m[3]+m[5]*m[6], |
- a22 = m[8]*m[0]-m[2]*m[6], |
- a32 = -m[5]*m[0]+m[2]*m[3], |
- a13 = m[7]*m[4]-m[4]*m[8], |
- a23 = -m[7]*m[0]+m[1]*m[6], |
- a33 = m[4]*m[0]-m[1]*m[3]; |
- var det = m[0]*(a11) + m[1]*(a12) + m[2]*(a13); |
- if (det == 0) // no inverse |
- return [1,0,0,0,1,0,0,0,1]; |
- var idet = 1 / det; |
- n[0] = idet*a11; |
- n[1] = idet*a21; |
- n[2] = idet*a31; |
- n[3] = idet*a12; |
- n[4] = idet*a22; |
- n[5] = idet*a32; |
- n[6] = idet*a13; |
- n[7] = idet*a23; |
- n[8] = idet*a33; |
- return n; |
- }, |
- |
- frustum : function (left, right, bottom, top, znear, zfar) { |
- var X = 2*znear/(right-left); |
- var Y = 2*znear/(top-bottom); |
- var A = (right+left)/(right-left); |
- var B = (top+bottom)/(top-bottom); |
- var C = -(zfar+znear)/(zfar-znear); |
- var D = -2*zfar*znear/(zfar-znear); |
- |
- return [ |
- X, 0, 0, 0, |
- 0, Y, 0, 0, |
- A, B, C, -1, |
- 0, 0, D, 0 |
- ]; |
- }, |
- |
- perspective : function (fovy, aspect, znear, zfar) { |
- var ymax = znear * Math.tan(fovy * Math.PI / 360.0); |
- var ymin = -ymax; |
- var xmin = ymin * aspect; |
- var xmax = ymax * aspect; |
- |
- return this.frustum(xmin, xmax, ymin, ymax, znear, zfar); |
- }, |
- |
- mul4x4 : function (a,b) { |
- return this.mul4x4InPlace(a,b,this.newIdentity()); |
- }, |
- |
- mul4x4InPlace : function (a, b, c) { |
- c[0] = b[0] * a[0] + |
- b[0+1] * a[4] + |
- b[0+2] * a[8] + |
- b[0+3] * a[12]; |
- c[0+1] = b[0] * a[1] + |
- b[0+1] * a[5] + |
- b[0+2] * a[9] + |
- b[0+3] * a[13]; |
- c[0+2] = b[0] * a[2] + |
- b[0+1] * a[6] + |
- b[0+2] * a[10] + |
- b[0+3] * a[14]; |
- c[0+3] = b[0] * a[3] + |
- b[0+1] * a[7] + |
- b[0+2] * a[11] + |
- b[0+3] * a[15]; |
- c[4] = b[4] * a[0] + |
- b[4+1] * a[4] + |
- b[4+2] * a[8] + |
- b[4+3] * a[12]; |
- c[4+1] = b[4] * a[1] + |
- b[4+1] * a[5] + |
- b[4+2] * a[9] + |
- b[4+3] * a[13]; |
- c[4+2] = b[4] * a[2] + |
- b[4+1] * a[6] + |
- b[4+2] * a[10] + |
- b[4+3] * a[14]; |
- c[4+3] = b[4] * a[3] + |
- b[4+1] * a[7] + |
- b[4+2] * a[11] + |
- b[4+3] * a[15]; |
- c[8] = b[8] * a[0] + |
- b[8+1] * a[4] + |
- b[8+2] * a[8] + |
- b[8+3] * a[12]; |
- c[8+1] = b[8] * a[1] + |
- b[8+1] * a[5] + |
- b[8+2] * a[9] + |
- b[8+3] * a[13]; |
- c[8+2] = b[8] * a[2] + |
- b[8+1] * a[6] + |
- b[8+2] * a[10] + |
- b[8+3] * a[14]; |
- c[8+3] = b[8] * a[3] + |
- b[8+1] * a[7] + |
- b[8+2] * a[11] + |
- b[8+3] * a[15]; |
- c[12] = b[12] * a[0] + |
- b[12+1] * a[4] + |
- b[12+2] * a[8] + |
- b[12+3] * a[12]; |
- c[12+1] = b[12] * a[1] + |
- b[12+1] * a[5] + |
- b[12+2] * a[9] + |
- b[12+3] * a[13]; |
- c[12+2] = b[12] * a[2] + |
- b[12+1] * a[6] + |
- b[12+2] * a[10] + |
- b[12+3] * a[14]; |
- c[12+3] = b[12] * a[3] + |
- b[12+1] * a[7] + |
- b[12+2] * a[11] + |
- b[12+3] * a[15]; |
- return c; |
- }, |
- |
- mulv4 : function (a, v) { |
- c = new Array(4); |
- for (var i=0; i<4; ++i) { |
- var x = 0; |
- for (var k=0; k<4; ++k) |
- x += v[k] * a[k*4+i]; |
- c[i] = x; |
- } |
- return c; |
- }, |
- |
- rotate : function (angle, axis) { |
- axis = Vec3.normalize(axis); |
- var x=axis[0], y=axis[1], z=axis[2]; |
- var c = Math.cos(angle); |
- var c1 = 1-c; |
- var s = Math.sin(angle); |
- return [ |
- x*x*c1+c, y*x*c1+z*s, z*x*c1-y*s, 0, |
- x*y*c1-z*s, y*y*c1+c, y*z*c1+x*s, 0, |
- x*z*c1+y*s, y*z*c1-x*s, z*z*c1+c, 0, |
- 0,0,0,1 |
- ]; |
- }, |
- rotateInPlace : function(angle, axis, m) { |
- axis = Vec3.normalize(axis); |
- var x=axis[0], y=axis[1], z=axis[2]; |
- var c = Math.cos(angle); |
- var c1 = 1-c; |
- var s = Math.sin(angle); |
- var tmpMatrix = this.tmpMatrix; |
- var tmpMatrix2 = this.tmpMatrix2; |
- tmpMatrix[0] = x*x*c1+c; tmpMatrix[1] = y*x*c1+z*s; tmpMatrix[2] = z*x*c1-y*s; tmpMatrix[3] = 0; |
- tmpMatrix[4] = x*y*c1-z*s; tmpMatrix[5] = y*y*c1+c; tmpMatrix[6] = y*z*c1+x*s; tmpMatrix[7] = 0; |
- tmpMatrix[8] = x*z*c1+y*s; tmpMatrix[9] = y*z*c1-x*s; tmpMatrix[10] = z*z*c1+c; tmpMatrix[11] = 0; |
- tmpMatrix[12] = 0; tmpMatrix[13] = 0; tmpMatrix[14] = 0; tmpMatrix[15] = 1; |
- this.copyMatrix(m, tmpMatrix2); |
- return this.mul4x4InPlace(tmpMatrix2, tmpMatrix, m); |
- }, |
- |
- scale : function(v) { |
- return [ |
- v[0], 0, 0, 0, |
- 0, v[1], 0, 0, |
- 0, 0, v[2], 0, |
- 0, 0, 0, 1 |
- ]; |
- }, |
- scale3 : function(x,y,z) { |
- return [ |
- x, 0, 0, 0, |
- 0, y, 0, 0, |
- 0, 0, z, 0, |
- 0, 0, 0, 1 |
- ]; |
- }, |
- scale1 : function(s) { |
- return [ |
- s, 0, 0, 0, |
- 0, s, 0, 0, |
- 0, 0, s, 0, |
- 0, 0, 0, 1 |
- ]; |
- }, |
- scale3InPlace : function(x, y, z, m) { |
- var tmpMatrix = this.tmpMatrix; |
- var tmpMatrix2 = this.tmpMatrix2; |
- tmpMatrix[0] = x; tmpMatrix[1] = 0; tmpMatrix[2] = 0; tmpMatrix[3] = 0; |
- tmpMatrix[4] = 0; tmpMatrix[5] = y; tmpMatrix[6] = 0; tmpMatrix[7] = 0; |
- tmpMatrix[8] = 0; tmpMatrix[9] = 0; tmpMatrix[10] = z; tmpMatrix[11] = 0; |
- tmpMatrix[12] = 0; tmpMatrix[13] = 0; tmpMatrix[14] = 0; tmpMatrix[15] = 1; |
- this.copyMatrix(m, tmpMatrix2); |
- return this.mul4x4InPlace(tmpMatrix2, tmpMatrix, m); |
- }, |
- scale1InPlace : function(s, m) { return this.scale3InPlace(s, s, s, m); }, |
- scaleInPlace : function(s, m) { return this.scale3InPlace(s[0],s[1],s[2],m); }, |
- |
- translate3 : function(x,y,z) { |
- return [ |
- 1, 0, 0, 0, |
- 0, 1, 0, 0, |
- 0, 0, 1, 0, |
- x, y, z, 1 |
- ]; |
- }, |
- |
- translate : function(v) { |
- return this.translate3(v[0], v[1], v[2]); |
- }, |
- tmpMatrix : [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0], |
- tmpMatrix2 : [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0], |
- translate3InPlace : function(x,y,z,m) { |
- var tmpMatrix = this.tmpMatrix; |
- var tmpMatrix2 = this.tmpMatrix2; |
- tmpMatrix[0] = 1; tmpMatrix[1] = 0; tmpMatrix[2] = 0; tmpMatrix[3] = 0; |
- tmpMatrix[4] = 0; tmpMatrix[5] = 1; tmpMatrix[6] = 0; tmpMatrix[7] = 0; |
- tmpMatrix[8] = 0; tmpMatrix[9] = 0; tmpMatrix[10] = 1; tmpMatrix[11] = 0; |
- tmpMatrix[12] = x; tmpMatrix[13] = y; tmpMatrix[14] = z; tmpMatrix[15] = 1; |
- this.copyMatrix(m, tmpMatrix2); |
- return this.mul4x4InPlace(tmpMatrix2, tmpMatrix, m); |
- }, |
- translateInPlace : function(v,m){ return this.translate3InPlace(v[0], v[1], v[2], m); }, |
- |
- lookAt : function (eye, center, up) { |
- var z = Vec3.direction(eye, center); |
- var x = Vec3.normalizeInPlace(Vec3.cross(up, z)); |
- var y = Vec3.normalizeInPlace(Vec3.cross(z, x)); |
- |
- var m = [ |
- x[0], y[0], z[0], 0, |
- x[1], y[1], z[1], 0, |
- x[2], y[2], z[2], 0, |
- 0, 0, 0, 1 |
- ]; |
- |
- var t = [ |
- 1, 0, 0, 0, |
- 0, 1, 0, 0, |
- 0, 0, 1, 0, |
- -eye[0], -eye[1], -eye[2], 1 |
- ]; |
- |
- return this.mul4x4(m,t); |
- }, |
- |
- transpose4x4 : function(m) { |
- return [ |
- m[0], m[4], m[8], m[12], |
- m[1], m[5], m[9], m[13], |
- m[2], m[6], m[10], m[14], |
- m[3], m[7], m[11], m[15] |
- ]; |
- }, |
- |
- transpose4x4InPlace : function(m) { |
- var tmp = 0.0; |
- tmp = m[1]; m[1] = m[4]; m[4] = tmp; |
- tmp = m[2]; m[2] = m[8]; m[8] = tmp; |
- tmp = m[3]; m[3] = m[12]; m[12] = tmp; |
- tmp = m[6]; m[6] = m[9]; m[9] = tmp; |
- tmp = m[7]; m[7] = m[13]; m[13] = tmp; |
- tmp = m[11]; m[11] = m[14]; m[14] = tmp; |
- return m; |
- }, |
- |
- transpose3x3 : function(m) { |
- return [ |
- m[0], m[3], m[6], |
- m[1], m[4], m[7], |
- m[2], m[5], m[8] |
- ]; |
- }, |
- |
- transpose3x3InPlace : function(m) { |
- var tmp = 0.0; |
- tmp = m[1]; m[1] = m[3]; m[3] = tmp; |
- tmp = m[2]; m[2] = m[6]; m[6] = tmp; |
- tmp = m[5]; m[5] = m[7]; m[7] = tmp; |
- return m; |
- }, |
-} |
- |
-Vec3 = { |
- make : function() { return [0,0,0]; }, |
- copy : function(v) { return [v[0],v[1],v[2]]; }, |
- |
- add : function (u,v) { |
- return [u[0]+v[0], u[1]+v[1], u[2]+v[2]]; |
- }, |
- |
- sub : function (u,v) { |
- return [u[0]-v[0], u[1]-v[1], u[2]-v[2]]; |
- }, |
- |
- negate : function (u) { |
- return [-u[0], -u[1], -u[2]]; |
- }, |
- |
- direction : function (u,v) { |
- return this.normalizeInPlace(this.sub(u,v)); |
- }, |
- |
- normalizeInPlace : function(v) { |
- var imag = 1.0 / Math.sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); |
- v[0] *= imag; v[1] *= imag; v[2] *= imag; |
- return v; |
- }, |
- |
- normalize : function(v) { |
- return this.normalizeInPlace(this.copy(v)); |
- }, |
- |
- scale : function(f, v) { |
- return [f*v[0], f*v[1], f*v[2]]; |
- }, |
- |
- dot : function(u,v) { |
- return u[0]*v[0] + u[1]*v[1] + u[2]*v[2]; |
- }, |
- |
- inner : function(u,v) { |
- return [u[0]*v[0], u[1]*v[1], u[2]*v[2]]; |
- }, |
- |
- cross : function(u,v) { |
- return [ |
- u[1]*v[2] - u[2]*v[1], |
- u[2]*v[0] - u[0]*v[2], |
- u[0]*v[1] - u[1]*v[0] |
- ]; |
- } |
-} |
- |
-Shader = function(gl){ |
- this.gl = gl; |
- this.shaders = []; |
- this.uniformLocations = {}; |
- this.attribLocations = {}; |
- for (var i=1; i<arguments.length; i++) { |
- this.shaders.push(arguments[i]); |
- } |
-} |
-Shader.prototype = { |
- id : null, |
- gl : null, |
- compiled : false, |
- shader : null, |
- shaders : [], |
- |
- destroy : function() { |
- if (this.shader != null) deleteShader(this.gl, this.shader); |
- }, |
- |
- compile : function() { |
- this.shader = loadShaderArray(this.gl, this.shaders); |
- }, |
- |
- use : function() { |
- if (this.shader == null) |
- this.compile(); |
- this.gl.useProgram(this.shader.program); |
- }, |
- |
- uniform1fv : function(name, value) { |
- var loc = this.uniform(name); |
- this.gl.uniform1fv(loc, value); |
- }, |
- |
- uniform2fv : function(name, value) { |
- var loc = this.uniform(name); |
- this.gl.uniform2fv(loc, value); |
- }, |
- |
- uniform3fv : function(name, value) { |
- var loc = this.uniform(name); |
- this.gl.uniform3fv(loc, value); |
- }, |
- |
- uniform4fv : function(name, value) { |
- var loc = this.uniform(name); |
- this.gl.uniform4fv(loc, value); |
- }, |
- |
- uniform1f : function(name, value) { |
- var loc = this.uniform(name); |
- this.gl.uniform1f(loc, value); |
- }, |
- |
- uniform2f : function(name, v1,v2) { |
- var loc = this.uniform(name); |
- this.gl.uniform2f(loc, v1,v2); |
- }, |
- |
- uniform3f : function(name, v1,v2,v3) { |
- var loc = this.uniform(name); |
- this.gl.uniform3f(loc, v1,v2,v3); |
- }, |
- |
- uniform4f : function(name, v1,v2,v3,v4) { |
- var loc = this.uniform(name); |
- this.gl.uniform4f(loc, v1, v2, v3, v4); |
- }, |
- |
- uniform1iv : function(name, value) { |
- var loc = this.uniform(name); |
- this.gl.uniform1iv(loc, value); |
- }, |
- |
- uniform2iv : function(name, value) { |
- var loc = this.uniform(name); |
- this.gl.uniform2iv(loc, value); |
- }, |
- |
- uniform3iv : function(name, value) { |
- var loc = this.uniform(name); |
- this.gl.uniform3iv(loc, value); |
- }, |
- |
- uniform4iv : function(name, value) { |
- var loc = this.uniform(name); |
- this.gl.uniform4iv(loc, value); |
- }, |
- |
- uniform1i : function(name, value) { |
- var loc = this.uniform(name); |
- this.gl.uniform1i(loc, value); |
- }, |
- |
- uniform2i : function(name, v1,v2) { |
- var loc = this.uniform(name); |
- this.gl.uniform2i(loc, v1,v2); |
- }, |
- |
- uniform3i : function(name, v1,v2,v3) { |
- var loc = this.uniform(name); |
- this.gl.uniform3i(loc, v1,v2,v3); |
- }, |
- |
- uniform4i : function(name, v1,v2,v3,v4) { |
- var loc = this.uniform(name); |
- this.gl.uniform4i(loc, v1, v2, v3, v4); |
- }, |
- |
- uniformMatrix4fv : function(name, value) { |
- var loc = this.uniform(name); |
- this.gl.uniformMatrix4fv(loc, false, value); |
- }, |
- |
- uniformMatrix3fv : function(name, value) { |
- var loc = this.uniform(name); |
- this.gl.uniformMatrix3fv(loc, false, value); |
- }, |
- |
- uniformMatrix2fv : function(name, value) { |
- var loc = this.uniform(name); |
- this.gl.uniformMatrix2fv(loc, false, value); |
- }, |
- |
- attrib : function(name) { |
- if (this.attribLocations[name] == null) { |
- var loc = this.gl.getAttribLocation(this.shader.program, name); |
- this.attribLocations[name] = loc; |
- } |
- return this.attribLocations[name]; |
- }, |
- |
- uniform : function(name) { |
- if (this.uniformLocations[name] == null) { |
- var loc = this.gl.getUniformLocation(this.shader.program, name); |
- this.uniformLocations[name] = loc; |
- } |
- return this.uniformLocations[name]; |
- } |
-} |
-Filter = function(gl, shader) { |
- Shader.apply(this, arguments); |
-} |
-Filter.prototype = new Shader(); |
-Filter.prototype.apply = function(init) { |
- this.use(); |
- var va = this.attrib("Vertex"); |
- var ta = this.attrib("Tex"); |
- var vbo = Quad.getCachedVBO(this.gl); |
- if (init) init(this); |
- vbo.draw(va, null, ta); |
-} |
- |
- |
-VBO = function(gl) { |
- this.gl = gl; |
- this.data = []; |
- this.elementsVBO = null; |
- for (var i=1; i<arguments.length; i++) { |
- if (arguments[i].elements) |
- this.elements = arguments[i]; |
- else |
- this.data.push(arguments[i]); |
- } |
-} |
- |
-VBO.prototype = { |
- initialized : false, |
- length : 0, |
- vbos : null, |
- type : 'TRIANGLES', |
- elementsVBO : null, |
- elements : null, |
- |
- setData : function() { |
- this.destroy(); |
- this.data = []; |
- for (var i=0; i<arguments.length; i++) { |
- if (arguments[i].elements) |
- this.elements = arguments[i]; |
- else |
- this.data.push(arguments[i]); |
- } |
- }, |
- |
- destroy : function() { |
- if (this.vbos != null) |
- for (var i=0; i<this.vbos.length; i++) |
- this.gl.deleteBuffer(this.vbos[i]); |
- if (this.elementsVBO != null) |
- this.gl.deleteBuffer(this.elementsVBO); |
- this.length = this.elementsLength = 0; |
- this.vbos = this.elementsVBO = null; |
- this.initialized = false; |
- }, |
- |
- init : function() { |
- this.destroy(); |
- var gl = this.gl; |
- |
- gl.getError(); |
- var vbos = []; |
- var length = 0; |
- for (var i=0; i<this.data.length; i++) |
- vbos.push(gl.createBuffer()); |
- if (this.elements != null) |
- this.elementsVBO = gl.createBuffer(); |
- try { |
- throwError(gl, "genBuffers"); |
- for (var i = 0; i<this.data.length; i++) { |
- var d = this.data[i]; |
- var dlen = Math.floor(d.data.length / d.size); |
- if (i == 0 || dlen < length) |
- length = dlen; |
- if (!d.floatArray) |
- d.floatArray = new Float32Array(d.data); |
- gl.bindBuffer(gl.ARRAY_BUFFER, vbos[i]); |
- throwError(gl, "bindBuffer"); |
- gl.bufferData(gl.ARRAY_BUFFER, d.floatArray, gl.STATIC_DRAW); |
- throwError(gl, "bufferData"); |
- } |
- if (this.elementsVBO != null) { |
- var d = this.elements; |
- this.elementsLength = d.data.length; |
- this.elementsType = d.type == gl.UNSIGNED_BYTE ? d.type : gl.UNSIGNED_SHORT; |
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.elementsVBO); |
- throwError(gl, "bindBuffer ELEMENT_ARRAY_BUFFER"); |
- if (this.elementsType == gl.UNSIGNED_SHORT && !d.ushortArray) { |
- d.ushortArray = new Uint16Array(d.data); |
- gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, d.ushortArray, gl.STATIC_DRAW); |
- } else if (this.elementsType == gl.UNSIGNED_BYTE && !d.ubyteArray) { |
- d.ubyteArray = new Uint8Array(d.data); |
- gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, d.ubyteArray, gl.STATIC_DRAW); |
- } |
- throwError(gl, "bufferData ELEMENT_ARRAY_BUFFER"); |
- } |
- } catch(e) { |
- for (var i=0; i<vbos.length; i++) |
- gl.deleteBuffer(vbos[i]); |
- throw(e); |
- } |
- |
- gl.bindBuffer(gl.ARRAY_BUFFER, null); |
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); |
- |
- this.length = length; |
- this.vbos = vbos; |
- |
- this.initialized = true; |
- }, |
- |
- use : function() { |
- if (!this.initialized) this.init(); |
- var gl = this.gl; |
- for (var i=0; i<arguments.length; i++) { |
- if (arguments[i] == null) continue; |
- gl.bindBuffer(gl.ARRAY_BUFFER, this.vbos[i]); |
- gl.vertexAttribPointer(arguments[i], this.data[i].size, gl.FLOAT, false, 0, 0); |
- gl.enableVertexAttribArray(arguments[i]); |
- } |
- if (this.elementsVBO != null) { |
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.elementsVBO); |
- } |
- }, |
- |
- draw : function() { |
- var args = []; |
- this.use.apply(this, arguments); |
- var gl = this.gl; |
- if (this.elementsVBO != null) { |
- gl.drawElements(gl[this.type], this.elementsLength, this.elementsType, 0); |
- } else { |
- gl.drawArrays(gl[this.type], 0, this.length); |
- } |
- } |
-} |
- |
-FBO = function(gl, width, height, use_depth) { |
- this.gl = gl; |
- this.width = width; |
- this.height = height; |
- if (use_depth != null) |
- this.useDepth = use_depth; |
-} |
-FBO.prototype = { |
- initialized : false, |
- useDepth : true, |
- fbo : null, |
- rbo : null, |
- texture : null, |
- |
- destroy : function() { |
- if (this.fbo) this.gl.deleteFramebuffer(this.fbo); |
- if (this.rbo) this.gl.deleteRenderbuffer(this.rbo); |
- if (this.texture) this.gl.deleteTexture(this.texture); |
- }, |
- |
- init : function() { |
- var gl = this.gl; |
- var w = this.width, h = this.height; |
- var fbo = this.fbo != null ? this.fbo : gl.createFramebuffer(); |
- var rb; |
- |
- gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); |
- checkError(gl, "FBO.init bindFramebuffer"); |
- if (this.useDepth) { |
- rb = this.rbo != null ? this.rbo : gl.createRenderbuffer(); |
- gl.bindRenderbuffer(gl.RENDERBUFFER, rb); |
- checkError(gl, "FBO.init bindRenderbuffer"); |
- gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, w, h); |
- checkError(gl, "FBO.init renderbufferStorage"); |
- } |
- |
- var tex = this.texture != null ? this.texture : gl.createTexture(); |
- gl.bindTexture(gl.TEXTURE_2D, tex); |
- try { |
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, w, h, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); |
- } catch (e) { // argh, no null texture support |
- var tmp = this.getTempCanvas(w,h); |
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, tmp); |
- } |
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); |
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); |
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); |
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); |
- checkError(gl, "FBO.init tex"); |
- |
- gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0); |
- checkError(gl, "FBO.init bind tex"); |
- |
- if (this.useDepth) { |
- gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rb); |
- checkError(gl, "FBO.init bind depth buffer"); |
- } |
- |
- var fbstat = gl.checkFramebufferStatus(gl.FRAMEBUFFER); |
- if (fbstat != gl.FRAMEBUFFER_COMPLETE) { |
- var glv; |
- for (var v in gl) { |
- try { glv = gl[v]; } catch (e) { glv = null; } |
- if (glv == fbstat) { fbstat = v; break; }} |
- log("Framebuffer status: " + fbstat); |
- } |
- checkError(gl, "FBO.init check fbo"); |
- |
- this.fbo = fbo; |
- this.rbo = rb; |
- this.texture = tex; |
- this.initialized = true; |
- }, |
- |
- getTempCanvas : function(w, h) { |
- if (!FBO.tempCanvas) { |
- FBO.tempCanvas = document.createElement('canvas'); |
- } |
- FBO.tempCanvas.width = w; |
- FBO.tempCanvas.height = h; |
- return FBO.tempCanvas; |
- }, |
- |
- use : function() { |
- if (!this.initialized) this.init(); |
- this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.fbo); |
- } |
-} |
- |
-function GLError(err, msg, fileName, lineNumber) { |
- this.message = msg; |
- this.glError = err; |
-} |
- |
-GLError.prototype = new Error(); |
- |
-function makeGLErrorWrapper(gl, fname) { |
- return (function() { |
- try { |
- var rv = gl[fname].apply(gl, arguments); |
- var err = gl.getError(); |
- if (err != gl.NO_ERROR) { |
- throw(new GLError( |
- err, "GL error "+getGLErrorAsString(gl, err)+" in "+fname)); |
- } |
- return rv; |
- } catch (e) { |
- if (e.glError !== undefined) { |
- throw e; |
- } |
- throw(new Error("Threw " + e.name + |
- " in " + fname + "\n" + |
- e.message + "\n" + |
- arguments.callee.caller)); |
- } |
- }); |
-} |
- |
-function wrapGLContext(gl) { |
- var wrap = {}; |
- for (var i in gl) { |
- try { |
- if (typeof gl[i] == 'function') { |
- wrap[i] = makeGLErrorWrapper(gl, i); |
- } else { |
- wrap[i] = gl[i]; |
- } |
- } catch (e) { |
- // log("wrapGLContext: Error accessing " + i); |
- } |
- } |
- wrap.getError = function(){ return gl.getError(); }; |
- return wrap; |
-} |
- |
-// Assert that f generates a specific GL error. |
-function assertGLError(gl, err, name, f) { |
- if (f == null) { f = name; name = null; } |
- var r = false; |
- var glErr = 0; |
- try { f(); } catch(e) { r=true; glErr = e.glError; } |
- if (glErr !== err) { |
- if (glErr === undefined) { |
- testFailed("assertGLError: UNEXPCETED EXCEPTION", name, f); |
- } else { |
- testFailed("assertGLError: expected: " + getGLErrorAsString(gl, err) + |
- " actual: " + getGLErrorAsString(gl, glErr), name, f); |
- } |
- return false; |
- } |
- return true; |
-} |
- |
-// Assert that f generates some GL error. Used in situations where it's |
-// ambigious which of multiple possible errors will be generated. |
-function assertSomeGLError(gl, name, f) { |
- if (f == null) { f = name; name = null; } |
- var r = false; |
- var glErr = 0; |
- var err = 0; |
- try { f(); } catch(e) { r=true; glErr = e.glError; } |
- if (glErr === 0) { |
- if (glErr === undefined) { |
- testFailed("assertGLError: UNEXPCETED EXCEPTION", name, f); |
- } else { |
- testFailed("assertGLError: expected: " + getGLErrorAsString(gl, err) + |
- " actual: " + getGLErrorAsString(gl, glErr), name, f); |
- } |
- return false; |
- } |
- return true; |
-} |
- |
-// Assert that f throws an exception but does not generate a GL error. |
-function assertThrowNoGLError(gl, name, f) { |
- if (f == null) { f = name; name = null; } |
- var r = false; |
- var glErr = undefined; |
- var exp; |
- try { f(); } catch(e) { r=true; glErr = e.glError; exp = e;} |
- if (!r) { |
- testFailed( |
- "assertThrowNoGError: should have thrown exception", name, f); |
- return false; |
- } else { |
- if (glErr !== undefined) { |
- testFailed( |
- "assertThrowNoGError: should be no GL error but generated: " + |
- getGLErrorAsString(gl, glErr), name, f); |
- return false; |
- } else { |
- // console.log("threw:" + exp); |
- } |
- } |
- return true; |
-} |
- |
-Quad = { |
- vertices : [ |
- -1,-1,0, |
- 1,-1,0, |
- -1,1,0, |
- 1,-1,0, |
- 1,1,0, |
- -1,1,0 |
- ], |
- normals : [ |
- 0,0,-1, |
- 0,0,-1, |
- 0,0,-1, |
- 0,0,-1, |
- 0,0,-1, |
- 0,0,-1 |
- ], |
- texcoords : [ |
- 0,0, |
- 1,0, |
- 0,1, |
- 1,0, |
- 1,1, |
- 0,1 |
- ], |
- indices : [0,1,2,1,5,2], |
- makeVBO : function(gl) { |
- return new VBO(gl, |
- {size:3, data: Quad.vertices}, |
- {size:3, data: Quad.normals}, |
- {size:2, data: Quad.texcoords} |
- ) |
- }, |
- cache: {}, |
- getCachedVBO : function(gl) { |
- if (!this.cache[gl]) |
- this.cache[gl] = this.makeVBO(gl); |
- return this.cache[gl]; |
- } |
-} |
-Cube = { |
- vertices : [ 0.5, -0.5, 0.5, // +X |
- 0.5, -0.5, -0.5, |
- 0.5, 0.5, -0.5, |
- 0.5, 0.5, 0.5, |
- |
- 0.5, 0.5, 0.5, // +Y |
- 0.5, 0.5, -0.5, |
- -0.5, 0.5, -0.5, |
- -0.5, 0.5, 0.5, |
- |
- 0.5, 0.5, 0.5, // +Z |
- -0.5, 0.5, 0.5, |
- -0.5, -0.5, 0.5, |
- 0.5, -0.5, 0.5, |
- |
- -0.5, -0.5, 0.5, // -X |
- -0.5, 0.5, 0.5, |
- -0.5, 0.5, -0.5, |
- -0.5, -0.5, -0.5, |
- |
- -0.5, -0.5, 0.5, // -Y |
- -0.5, -0.5, -0.5, |
- 0.5, -0.5, -0.5, |
- 0.5, -0.5, 0.5, |
- |
- -0.5, -0.5, -0.5, // -Z |
- -0.5, 0.5, -0.5, |
- 0.5, 0.5, -0.5, |
- 0.5, -0.5, -0.5, |
- ], |
- |
- normals : [ 1, 0, 0, |
- 1, 0, 0, |
- 1, 0, 0, |
- 1, 0, 0, |
- |
- 0, 1, 0, |
- 0, 1, 0, |
- 0, 1, 0, |
- 0, 1, 0, |
- |
- 0, 0, 1, |
- 0, 0, 1, |
- 0, 0, 1, |
- 0, 0, 1, |
- |
- -1, 0, 0, |
- -1, 0, 0, |
- -1, 0, 0, |
- -1, 0, 0, |
- |
- 0,-1, 0, |
- 0,-1, 0, |
- 0,-1, 0, |
- 0,-1, 0, |
- |
- 0, 0,-1, |
- 0, 0,-1, |
- 0, 0,-1, |
- 0, 0,-1 |
- ], |
- |
- indices : [], |
- create : function(){ |
- for (var i = 0; i < 6; i++) { |
- Cube.indices.push(i*4 + 0); |
- Cube.indices.push(i*4 + 1); |
- Cube.indices.push(i*4 + 3); |
- Cube.indices.push(i*4 + 1); |
- Cube.indices.push(i*4 + 2); |
- Cube.indices.push(i*4 + 3); |
- } |
- }, |
- |
- makeVBO : function(gl) { |
- return new VBO(gl, |
- {size:3, data: Cube.vertices}, |
- {size:3, data: Cube.normals}, |
- {elements: true, data: Cube.indices} |
- ) |
- }, |
- cache : {}, |
- getCachedVBO : function(gl) { |
- if (!this.cache[gl]) |
- this.cache[gl] = this.makeVBO(gl); |
- return this.cache[gl]; |
- } |
-} |
-Cube.create(); |
- |
-Sphere = { |
- vertices : [], |
- normals : [], |
- indices : [], |
- create : function(){ |
- var r = 0.75; |
- function vert(theta, phi) |
- { |
- var r = 0.75; |
- var x, y, z, nx, ny, nz; |
- |
- nx = Math.sin(theta) * Math.cos(phi); |
- ny = Math.sin(phi); |
- nz = Math.cos(theta) * Math.cos(phi); |
- Sphere.normals.push(nx); |
- Sphere.normals.push(ny); |
- Sphere.normals.push(nz); |
- |
- x = r * Math.sin(theta) * Math.cos(phi); |
- y = r * Math.sin(phi); |
- z = r * Math.cos(theta) * Math.cos(phi); |
- Sphere.vertices.push(x); |
- Sphere.vertices.push(y); |
- Sphere.vertices.push(z); |
- } |
- for (var phi = -Math.PI/2; phi < Math.PI/2; phi += Math.PI/20) { |
- var phi2 = phi + Math.PI/20; |
- for (var theta = -Math.PI/2; theta <= Math.PI/2; theta += Math.PI/20) { |
- vert(theta, phi); |
- vert(theta, phi2); |
- } |
- } |
- } |
-} |
- |
-Sphere.create(); |
- |
-initGL_CONTEXT_ID = function(){ |
- var c = document.createElement('canvas'); |
- var contextNames = ['webgl', 'experimental-webgl']; |
- GL_CONTEXT_ID = null; |
- for (var i=0; i<contextNames.length; i++) { |
- try { |
- if (c.getContext(contextNames[i])) { |
- GL_CONTEXT_ID = contextNames[i]; |
- break; |
- } |
- } catch (e) {} |
- } |
- if (!GL_CONTEXT_ID) { |
- log("No WebGL context found. Unable to run tests."); |
- } |
-} |
- |
-initGL_CONTEXT_ID(); |