Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(258)

Side by Side Diff: conformance/more/util.js

Issue 41503006: Add ToT WebGL conformance tests : part 8 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/webgl/sdk/tests/
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « conformance/more/unit.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
## -0,0 +1 ##
+LF
\ No newline at end of property
OLDNEW
(Empty)
1 /*
2 Utilities for the OpenGL ES 2.0 HTML Canvas context
3 */
4
5 /*
6 ** Copyright (c) 2012 The Khronos Group Inc.
7 **
8 ** Permission is hereby granted, free of charge, to any person obtaining a
9 ** copy of this software and/or associated documentation files (the
10 ** "Materials"), to deal in the Materials without restriction, including
11 ** without limitation the rights to use, copy, modify, merge, publish,
12 ** distribute, sublicense, and/or sell copies of the Materials, and to
13 ** permit persons to whom the Materials are furnished to do so, subject to
14 ** the following conditions:
15 **
16 ** The above copyright notice and this permission notice shall be included
17 ** in all copies or substantial portions of the Materials.
18 **
19 ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23 ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
26 */
27
28 function loadTexture(gl, elem, mipmaps) {
29 var tex = gl.createTexture();
30 gl.bindTexture(gl.TEXTURE_2D, tex);
31 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, elem);
32 if (mipmaps != false)
33 gl.generateMipmap(gl.TEXTURE_2D);
34 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
35 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
36 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
37 if (mipmaps)
38 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINE AR);
39 else
40 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
41 return tex;
42 }
43
44 function getShader(gl, id) {
45 var shaderScript = document.getElementById(id);
46 if (!shaderScript) {
47 throw(new Error("No shader element with id: "+id));
48 }
49
50 var str = "";
51 var k = shaderScript.firstChild;
52 while (k) {
53 if (k.nodeType == 3)
54 str += k.textContent;
55 k = k.nextSibling;
56 }
57
58 var shader;
59 if (shaderScript.type == "x-shader/x-fragment") {
60 shader = gl.createShader(gl.FRAGMENT_SHADER);
61 } else if (shaderScript.type == "x-shader/x-vertex") {
62 shader = gl.createShader(gl.VERTEX_SHADER);
63 } else {
64 throw(new Error("Unknown shader type "+shaderScript.type));
65 }
66
67 gl.shaderSource(shader, str);
68 gl.compileShader(shader);
69
70 if (gl.getShaderParameter(shader, gl.COMPILE_STATUS) != 1) {
71 var ilog = gl.getShaderInfoLog(shader);
72 gl.deleteShader(shader);
73 throw(new Error("Failed to compile shader "+shaderScript.id + ", Shader info log: " + ilog));
74 }
75 return shader;
76 }
77
78 function loadShaderArray(gl, shaders) {
79 var id = gl.createProgram();
80 var shaderObjs = [];
81 for (var i=0; i<shaders.length; ++i) {
82 try {
83 var sh = getShader(gl, shaders[i]);
84 shaderObjs.push(sh);
85 gl.attachShader(id, sh);
86 } catch (e) {
87 var pr = {program: id, shaders: shaderObjs};
88 deleteShader(gl, pr);
89 throw (e);
90 }
91 }
92 var prog = {program: id, shaders: shaderObjs};
93 gl.linkProgram(id);
94 gl.validateProgram(id);
95 if (gl.getProgramParameter(id, gl.LINK_STATUS) != 1) {
96 deleteShader(gl,prog);
97 throw(new Error("Failed to link shader"));
98 }
99 if (gl.getProgramParameter(id, gl.VALIDATE_STATUS) != 1) {
100 deleteShader(gl,prog);
101 throw(new Error("Failed to validate shader"));
102 }
103 return prog;
104 }
105 function loadShader(gl) {
106 var sh = [];
107 for (var i=1; i<arguments.length; ++i)
108 sh.push(arguments[i]);
109 return loadShaderArray(gl, sh);
110 }
111
112 function deleteShader(gl, sh) {
113 gl.useProgram(null);
114 sh.shaders.forEach(function(s){
115 gl.detachShader(sh.program, s);
116 gl.deleteShader(s);
117 });
118 gl.deleteProgram(sh.program);
119 }
120
121 function getGLErrorAsString(ctx, err) {
122 if (err === ctx.NO_ERROR) {
123 return "NO_ERROR";
124 }
125 for (var name in ctx) {
126 if (ctx[name] === err) {
127 return name;
128 }
129 }
130 return err.toString();
131 }
132
133 function checkError(gl, msg) {
134 var e = gl.getError();
135 if (e != gl.NO_ERROR) {
136 log("Error " + getGLErrorAsString(gl, e) + " at " + msg);
137 }
138 return e;
139 }
140
141 function throwError(gl, msg) {
142 var e = gl.getError();
143 if (e != 0) {
144 throw(new Error("Error " + getGLErrorAsString(gl, e) + " at " + msg));
145 }
146 }
147
148 Math.cot = function(z) { return 1.0 / Math.tan(z); }
149
150 /*
151 Matrix utilities, using the OpenGL element order where
152 the last 4 elements are the translation column.
153
154 Uses flat arrays as matrices for performance.
155
156 Most operations have in-place variants to avoid allocating temporary matrices.
157
158 Naming logic:
159 Matrix.method operates on a 4x4 Matrix and returns a new Matrix.
160 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)))
161 Matrix.method[3x3]InPlace(args, target) stores its result in the target matr ix.
162
163 Matrix.scale([sx, sy, sz]) -- non-uniform scale by vector
164 Matrix.scale1(s) -- uniform scale by scalar
165 Matrix.scale3(sx, sy, sz) -- non-uniform scale by scalars
166
167 Ditto for translate.
168 */
169 Matrix = {
170 identity : [
171 1.0, 0.0, 0.0, 0.0,
172 0.0, 1.0, 0.0, 0.0,
173 0.0, 0.0, 1.0, 0.0,
174 0.0, 0.0, 0.0, 1.0
175 ],
176
177 newIdentity : function() {
178 return [
179 1.0, 0.0, 0.0, 0.0,
180 0.0, 1.0, 0.0, 0.0,
181 0.0, 0.0, 1.0, 0.0,
182 0.0, 0.0, 0.0, 1.0
183 ];
184 },
185
186 newIdentity3x3 : function() {
187 return [
188 1.0, 0.0, 0.0,
189 0.0, 1.0, 0.0,
190 0.0, 0.0, 1.0
191 ];
192 },
193
194 copyMatrix : function(src, dst) {
195 for (var i=0; i<16; i++) dst[i] = src[i];
196 return dst;
197 },
198
199 to3x3 : function(m) {
200 return [
201 m[0], m[1], m[2],
202 m[4], m[5], m[6],
203 m[8], m[9], m[10]
204 ];
205 },
206
207 // orthonormal matrix inverse
208 inverseON : function(m) {
209 var n = this.transpose4x4(m);
210 var t = [m[12], m[13], m[14]];
211 n[3] = n[7] = n[11] = 0;
212 n[12] = -Vec3.dot([n[0], n[4], n[8]], t);
213 n[13] = -Vec3.dot([n[1], n[5], n[9]], t);
214 n[14] = -Vec3.dot([n[2], n[6], n[10]], t);
215 return n;
216 },
217
218 inverseTo3x3 : function(m) {
219 return this.inverse4x4to3x3InPlace(m, this.newIdentity3x3());
220 },
221
222 inverseTo3x3InPlace : function(m,n) {
223 var a11 = m[10]*m[5]-m[6]*m[9],
224 a21 = -m[10]*m[1]+m[2]*m[9],
225 a31 = m[6]*m[1]-m[2]*m[5],
226 a12 = -m[10]*m[4]+m[6]*m[8],
227 a22 = m[10]*m[0]-m[2]*m[8],
228 a32 = -m[6]*m[0]+m[2]*m[4],
229 a13 = m[9]*m[4]-m[5]*m[8],
230 a23 = -m[9]*m[0]+m[1]*m[8],
231 a33 = m[5]*m[0]-m[1]*m[4];
232 var det = m[0]*(a11) + m[1]*(a12) + m[2]*(a13);
233 if (det == 0) // no inverse
234 return [1,0,0,0,1,0,0,0,1];
235 var idet = 1 / det;
236 n[0] = idet*a11;
237 n[1] = idet*a21;
238 n[2] = idet*a31;
239 n[3] = idet*a12;
240 n[4] = idet*a22;
241 n[5] = idet*a32;
242 n[6] = idet*a13;
243 n[7] = idet*a23;
244 n[8] = idet*a33;
245 return n;
246 },
247
248 inverse3x3 : function(m) {
249 return this.inverse3x3InPlace(m, this.newIdentity3x3());
250 },
251
252 inverse3x3InPlace : function(m,n) {
253 var a11 = m[8]*m[4]-m[5]*m[7],
254 a21 = -m[8]*m[1]+m[2]*m[7],
255 a31 = m[5]*m[1]-m[2]*m[4],
256 a12 = -m[8]*m[3]+m[5]*m[6],
257 a22 = m[8]*m[0]-m[2]*m[6],
258 a32 = -m[5]*m[0]+m[2]*m[3],
259 a13 = m[7]*m[4]-m[4]*m[8],
260 a23 = -m[7]*m[0]+m[1]*m[6],
261 a33 = m[4]*m[0]-m[1]*m[3];
262 var det = m[0]*(a11) + m[1]*(a12) + m[2]*(a13);
263 if (det == 0) // no inverse
264 return [1,0,0,0,1,0,0,0,1];
265 var idet = 1 / det;
266 n[0] = idet*a11;
267 n[1] = idet*a21;
268 n[2] = idet*a31;
269 n[3] = idet*a12;
270 n[4] = idet*a22;
271 n[5] = idet*a32;
272 n[6] = idet*a13;
273 n[7] = idet*a23;
274 n[8] = idet*a33;
275 return n;
276 },
277
278 frustum : function (left, right, bottom, top, znear, zfar) {
279 var X = 2*znear/(right-left);
280 var Y = 2*znear/(top-bottom);
281 var A = (right+left)/(right-left);
282 var B = (top+bottom)/(top-bottom);
283 var C = -(zfar+znear)/(zfar-znear);
284 var D = -2*zfar*znear/(zfar-znear);
285
286 return [
287 X, 0, 0, 0,
288 0, Y, 0, 0,
289 A, B, C, -1,
290 0, 0, D, 0
291 ];
292 },
293
294 perspective : function (fovy, aspect, znear, zfar) {
295 var ymax = znear * Math.tan(fovy * Math.PI / 360.0);
296 var ymin = -ymax;
297 var xmin = ymin * aspect;
298 var xmax = ymax * aspect;
299
300 return this.frustum(xmin, xmax, ymin, ymax, znear, zfar);
301 },
302
303 mul4x4 : function (a,b) {
304 return this.mul4x4InPlace(a,b,this.newIdentity());
305 },
306
307 mul4x4InPlace : function (a, b, c) {
308 c[0] = b[0] * a[0] +
309 b[0+1] * a[4] +
310 b[0+2] * a[8] +
311 b[0+3] * a[12];
312 c[0+1] = b[0] * a[1] +
313 b[0+1] * a[5] +
314 b[0+2] * a[9] +
315 b[0+3] * a[13];
316 c[0+2] = b[0] * a[2] +
317 b[0+1] * a[6] +
318 b[0+2] * a[10] +
319 b[0+3] * a[14];
320 c[0+3] = b[0] * a[3] +
321 b[0+1] * a[7] +
322 b[0+2] * a[11] +
323 b[0+3] * a[15];
324 c[4] = b[4] * a[0] +
325 b[4+1] * a[4] +
326 b[4+2] * a[8] +
327 b[4+3] * a[12];
328 c[4+1] = b[4] * a[1] +
329 b[4+1] * a[5] +
330 b[4+2] * a[9] +
331 b[4+3] * a[13];
332 c[4+2] = b[4] * a[2] +
333 b[4+1] * a[6] +
334 b[4+2] * a[10] +
335 b[4+3] * a[14];
336 c[4+3] = b[4] * a[3] +
337 b[4+1] * a[7] +
338 b[4+2] * a[11] +
339 b[4+3] * a[15];
340 c[8] = b[8] * a[0] +
341 b[8+1] * a[4] +
342 b[8+2] * a[8] +
343 b[8+3] * a[12];
344 c[8+1] = b[8] * a[1] +
345 b[8+1] * a[5] +
346 b[8+2] * a[9] +
347 b[8+3] * a[13];
348 c[8+2] = b[8] * a[2] +
349 b[8+1] * a[6] +
350 b[8+2] * a[10] +
351 b[8+3] * a[14];
352 c[8+3] = b[8] * a[3] +
353 b[8+1] * a[7] +
354 b[8+2] * a[11] +
355 b[8+3] * a[15];
356 c[12] = b[12] * a[0] +
357 b[12+1] * a[4] +
358 b[12+2] * a[8] +
359 b[12+3] * a[12];
360 c[12+1] = b[12] * a[1] +
361 b[12+1] * a[5] +
362 b[12+2] * a[9] +
363 b[12+3] * a[13];
364 c[12+2] = b[12] * a[2] +
365 b[12+1] * a[6] +
366 b[12+2] * a[10] +
367 b[12+3] * a[14];
368 c[12+3] = b[12] * a[3] +
369 b[12+1] * a[7] +
370 b[12+2] * a[11] +
371 b[12+3] * a[15];
372 return c;
373 },
374
375 mulv4 : function (a, v) {
376 c = new Array(4);
377 for (var i=0; i<4; ++i) {
378 var x = 0;
379 for (var k=0; k<4; ++k)
380 x += v[k] * a[k*4+i];
381 c[i] = x;
382 }
383 return c;
384 },
385
386 rotate : function (angle, axis) {
387 axis = Vec3.normalize(axis);
388 var x=axis[0], y=axis[1], z=axis[2];
389 var c = Math.cos(angle);
390 var c1 = 1-c;
391 var s = Math.sin(angle);
392 return [
393 x*x*c1+c, y*x*c1+z*s, z*x*c1-y*s, 0,
394 x*y*c1-z*s, y*y*c1+c, y*z*c1+x*s, 0,
395 x*z*c1+y*s, y*z*c1-x*s, z*z*c1+c, 0,
396 0,0,0,1
397 ];
398 },
399 rotateInPlace : function(angle, axis, m) {
400 axis = Vec3.normalize(axis);
401 var x=axis[0], y=axis[1], z=axis[2];
402 var c = Math.cos(angle);
403 var c1 = 1-c;
404 var s = Math.sin(angle);
405 var tmpMatrix = this.tmpMatrix;
406 var tmpMatrix2 = this.tmpMatrix2;
407 tmpMatrix[0] = x*x*c1+c; tmpMatrix[1] = y*x*c1+z*s; tmpMatrix[2] = z*x*c1-y* s; tmpMatrix[3] = 0;
408 tmpMatrix[4] = x*y*c1-z*s; tmpMatrix[5] = y*y*c1+c; tmpMatrix[6] = y*z*c1+x* s; tmpMatrix[7] = 0;
409 tmpMatrix[8] = x*z*c1+y*s; tmpMatrix[9] = y*z*c1-x*s; tmpMatrix[10] = z*z*c1 +c; tmpMatrix[11] = 0;
410 tmpMatrix[12] = 0; tmpMatrix[13] = 0; tmpMatrix[14] = 0; tmpMatrix[15] = 1;
411 this.copyMatrix(m, tmpMatrix2);
412 return this.mul4x4InPlace(tmpMatrix2, tmpMatrix, m);
413 },
414
415 scale : function(v) {
416 return [
417 v[0], 0, 0, 0,
418 0, v[1], 0, 0,
419 0, 0, v[2], 0,
420 0, 0, 0, 1
421 ];
422 },
423 scale3 : function(x,y,z) {
424 return [
425 x, 0, 0, 0,
426 0, y, 0, 0,
427 0, 0, z, 0,
428 0, 0, 0, 1
429 ];
430 },
431 scale1 : function(s) {
432 return [
433 s, 0, 0, 0,
434 0, s, 0, 0,
435 0, 0, s, 0,
436 0, 0, 0, 1
437 ];
438 },
439 scale3InPlace : function(x, y, z, m) {
440 var tmpMatrix = this.tmpMatrix;
441 var tmpMatrix2 = this.tmpMatrix2;
442 tmpMatrix[0] = x; tmpMatrix[1] = 0; tmpMatrix[2] = 0; tmpMatrix[3] = 0;
443 tmpMatrix[4] = 0; tmpMatrix[5] = y; tmpMatrix[6] = 0; tmpMatrix[7] = 0;
444 tmpMatrix[8] = 0; tmpMatrix[9] = 0; tmpMatrix[10] = z; tmpMatrix[11] = 0;
445 tmpMatrix[12] = 0; tmpMatrix[13] = 0; tmpMatrix[14] = 0; tmpMatrix[15] = 1;
446 this.copyMatrix(m, tmpMatrix2);
447 return this.mul4x4InPlace(tmpMatrix2, tmpMatrix, m);
448 },
449 scale1InPlace : function(s, m) { return this.scale3InPlace(s, s, s, m); },
450 scaleInPlace : function(s, m) { return this.scale3InPlace(s[0],s[1],s[2],m); } ,
451
452 translate3 : function(x,y,z) {
453 return [
454 1, 0, 0, 0,
455 0, 1, 0, 0,
456 0, 0, 1, 0,
457 x, y, z, 1
458 ];
459 },
460
461 translate : function(v) {
462 return this.translate3(v[0], v[1], v[2]);
463 },
464 tmpMatrix : [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0],
465 tmpMatrix2 : [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0],
466 translate3InPlace : function(x,y,z,m) {
467 var tmpMatrix = this.tmpMatrix;
468 var tmpMatrix2 = this.tmpMatrix2;
469 tmpMatrix[0] = 1; tmpMatrix[1] = 0; tmpMatrix[2] = 0; tmpMatrix[3] = 0;
470 tmpMatrix[4] = 0; tmpMatrix[5] = 1; tmpMatrix[6] = 0; tmpMatrix[7] = 0;
471 tmpMatrix[8] = 0; tmpMatrix[9] = 0; tmpMatrix[10] = 1; tmpMatrix[11] = 0;
472 tmpMatrix[12] = x; tmpMatrix[13] = y; tmpMatrix[14] = z; tmpMatrix[15] = 1;
473 this.copyMatrix(m, tmpMatrix2);
474 return this.mul4x4InPlace(tmpMatrix2, tmpMatrix, m);
475 },
476 translateInPlace : function(v,m){ return this.translate3InPlace(v[0], v[1], v[ 2], m); },
477
478 lookAt : function (eye, center, up) {
479 var z = Vec3.direction(eye, center);
480 var x = Vec3.normalizeInPlace(Vec3.cross(up, z));
481 var y = Vec3.normalizeInPlace(Vec3.cross(z, x));
482
483 var m = [
484 x[0], y[0], z[0], 0,
485 x[1], y[1], z[1], 0,
486 x[2], y[2], z[2], 0,
487 0, 0, 0, 1
488 ];
489
490 var t = [
491 1, 0, 0, 0,
492 0, 1, 0, 0,
493 0, 0, 1, 0,
494 -eye[0], -eye[1], -eye[2], 1
495 ];
496
497 return this.mul4x4(m,t);
498 },
499
500 transpose4x4 : function(m) {
501 return [
502 m[0], m[4], m[8], m[12],
503 m[1], m[5], m[9], m[13],
504 m[2], m[6], m[10], m[14],
505 m[3], m[7], m[11], m[15]
506 ];
507 },
508
509 transpose4x4InPlace : function(m) {
510 var tmp = 0.0;
511 tmp = m[1]; m[1] = m[4]; m[4] = tmp;
512 tmp = m[2]; m[2] = m[8]; m[8] = tmp;
513 tmp = m[3]; m[3] = m[12]; m[12] = tmp;
514 tmp = m[6]; m[6] = m[9]; m[9] = tmp;
515 tmp = m[7]; m[7] = m[13]; m[13] = tmp;
516 tmp = m[11]; m[11] = m[14]; m[14] = tmp;
517 return m;
518 },
519
520 transpose3x3 : function(m) {
521 return [
522 m[0], m[3], m[6],
523 m[1], m[4], m[7],
524 m[2], m[5], m[8]
525 ];
526 },
527
528 transpose3x3InPlace : function(m) {
529 var tmp = 0.0;
530 tmp = m[1]; m[1] = m[3]; m[3] = tmp;
531 tmp = m[2]; m[2] = m[6]; m[6] = tmp;
532 tmp = m[5]; m[5] = m[7]; m[7] = tmp;
533 return m;
534 },
535 }
536
537 Vec3 = {
538 make : function() { return [0,0,0]; },
539 copy : function(v) { return [v[0],v[1],v[2]]; },
540
541 add : function (u,v) {
542 return [u[0]+v[0], u[1]+v[1], u[2]+v[2]];
543 },
544
545 sub : function (u,v) {
546 return [u[0]-v[0], u[1]-v[1], u[2]-v[2]];
547 },
548
549 negate : function (u) {
550 return [-u[0], -u[1], -u[2]];
551 },
552
553 direction : function (u,v) {
554 return this.normalizeInPlace(this.sub(u,v));
555 },
556
557 normalizeInPlace : function(v) {
558 var imag = 1.0 / Math.sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
559 v[0] *= imag; v[1] *= imag; v[2] *= imag;
560 return v;
561 },
562
563 normalize : function(v) {
564 return this.normalizeInPlace(this.copy(v));
565 },
566
567 scale : function(f, v) {
568 return [f*v[0], f*v[1], f*v[2]];
569 },
570
571 dot : function(u,v) {
572 return u[0]*v[0] + u[1]*v[1] + u[2]*v[2];
573 },
574
575 inner : function(u,v) {
576 return [u[0]*v[0], u[1]*v[1], u[2]*v[2]];
577 },
578
579 cross : function(u,v) {
580 return [
581 u[1]*v[2] - u[2]*v[1],
582 u[2]*v[0] - u[0]*v[2],
583 u[0]*v[1] - u[1]*v[0]
584 ];
585 }
586 }
587
588 Shader = function(gl){
589 this.gl = gl;
590 this.shaders = [];
591 this.uniformLocations = {};
592 this.attribLocations = {};
593 for (var i=1; i<arguments.length; i++) {
594 this.shaders.push(arguments[i]);
595 }
596 }
597 Shader.prototype = {
598 id : null,
599 gl : null,
600 compiled : false,
601 shader : null,
602 shaders : [],
603
604 destroy : function() {
605 if (this.shader != null) deleteShader(this.gl, this.shader);
606 },
607
608 compile : function() {
609 this.shader = loadShaderArray(this.gl, this.shaders);
610 },
611
612 use : function() {
613 if (this.shader == null)
614 this.compile();
615 this.gl.useProgram(this.shader.program);
616 },
617
618 uniform1fv : function(name, value) {
619 var loc = this.uniform(name);
620 this.gl.uniform1fv(loc, value);
621 },
622
623 uniform2fv : function(name, value) {
624 var loc = this.uniform(name);
625 this.gl.uniform2fv(loc, value);
626 },
627
628 uniform3fv : function(name, value) {
629 var loc = this.uniform(name);
630 this.gl.uniform3fv(loc, value);
631 },
632
633 uniform4fv : function(name, value) {
634 var loc = this.uniform(name);
635 this.gl.uniform4fv(loc, value);
636 },
637
638 uniform1f : function(name, value) {
639 var loc = this.uniform(name);
640 this.gl.uniform1f(loc, value);
641 },
642
643 uniform2f : function(name, v1,v2) {
644 var loc = this.uniform(name);
645 this.gl.uniform2f(loc, v1,v2);
646 },
647
648 uniform3f : function(name, v1,v2,v3) {
649 var loc = this.uniform(name);
650 this.gl.uniform3f(loc, v1,v2,v3);
651 },
652
653 uniform4f : function(name, v1,v2,v3,v4) {
654 var loc = this.uniform(name);
655 this.gl.uniform4f(loc, v1, v2, v3, v4);
656 },
657
658 uniform1iv : function(name, value) {
659 var loc = this.uniform(name);
660 this.gl.uniform1iv(loc, value);
661 },
662
663 uniform2iv : function(name, value) {
664 var loc = this.uniform(name);
665 this.gl.uniform2iv(loc, value);
666 },
667
668 uniform3iv : function(name, value) {
669 var loc = this.uniform(name);
670 this.gl.uniform3iv(loc, value);
671 },
672
673 uniform4iv : function(name, value) {
674 var loc = this.uniform(name);
675 this.gl.uniform4iv(loc, value);
676 },
677
678 uniform1i : function(name, value) {
679 var loc = this.uniform(name);
680 this.gl.uniform1i(loc, value);
681 },
682
683 uniform2i : function(name, v1,v2) {
684 var loc = this.uniform(name);
685 this.gl.uniform2i(loc, v1,v2);
686 },
687
688 uniform3i : function(name, v1,v2,v3) {
689 var loc = this.uniform(name);
690 this.gl.uniform3i(loc, v1,v2,v3);
691 },
692
693 uniform4i : function(name, v1,v2,v3,v4) {
694 var loc = this.uniform(name);
695 this.gl.uniform4i(loc, v1, v2, v3, v4);
696 },
697
698 uniformMatrix4fv : function(name, value) {
699 var loc = this.uniform(name);
700 this.gl.uniformMatrix4fv(loc, false, value);
701 },
702
703 uniformMatrix3fv : function(name, value) {
704 var loc = this.uniform(name);
705 this.gl.uniformMatrix3fv(loc, false, value);
706 },
707
708 uniformMatrix2fv : function(name, value) {
709 var loc = this.uniform(name);
710 this.gl.uniformMatrix2fv(loc, false, value);
711 },
712
713 attrib : function(name) {
714 if (this.attribLocations[name] == null) {
715 var loc = this.gl.getAttribLocation(this.shader.program, name);
716 this.attribLocations[name] = loc;
717 }
718 return this.attribLocations[name];
719 },
720
721 uniform : function(name) {
722 if (this.uniformLocations[name] == null) {
723 var loc = this.gl.getUniformLocation(this.shader.program, name);
724 this.uniformLocations[name] = loc;
725 }
726 return this.uniformLocations[name];
727 }
728 }
729 Filter = function(gl, shader) {
730 Shader.apply(this, arguments);
731 }
732 Filter.prototype = new Shader();
733 Filter.prototype.apply = function(init) {
734 this.use();
735 var va = this.attrib("Vertex");
736 var ta = this.attrib("Tex");
737 var vbo = Quad.getCachedVBO(this.gl);
738 if (init) init(this);
739 vbo.draw(va, null, ta);
740 }
741
742
743 VBO = function(gl) {
744 this.gl = gl;
745 this.data = [];
746 this.elementsVBO = null;
747 for (var i=1; i<arguments.length; i++) {
748 if (arguments[i].elements)
749 this.elements = arguments[i];
750 else
751 this.data.push(arguments[i]);
752 }
753 }
754
755 VBO.prototype = {
756 initialized : false,
757 length : 0,
758 vbos : null,
759 type : 'TRIANGLES',
760 elementsVBO : null,
761 elements : null,
762
763 setData : function() {
764 this.destroy();
765 this.data = [];
766 for (var i=0; i<arguments.length; i++) {
767 if (arguments[i].elements)
768 this.elements = arguments[i];
769 else
770 this.data.push(arguments[i]);
771 }
772 },
773
774 destroy : function() {
775 if (this.vbos != null)
776 for (var i=0; i<this.vbos.length; i++)
777 this.gl.deleteBuffer(this.vbos[i]);
778 if (this.elementsVBO != null)
779 this.gl.deleteBuffer(this.elementsVBO);
780 this.length = this.elementsLength = 0;
781 this.vbos = this.elementsVBO = null;
782 this.initialized = false;
783 },
784
785 init : function() {
786 this.destroy();
787 var gl = this.gl;
788
789 gl.getError();
790 var vbos = [];
791 var length = 0;
792 for (var i=0; i<this.data.length; i++)
793 vbos.push(gl.createBuffer());
794 if (this.elements != null)
795 this.elementsVBO = gl.createBuffer();
796 try {
797 throwError(gl, "genBuffers");
798 for (var i = 0; i<this.data.length; i++) {
799 var d = this.data[i];
800 var dlen = Math.floor(d.data.length / d.size);
801 if (i == 0 || dlen < length)
802 length = dlen;
803 if (!d.floatArray)
804 d.floatArray = new Float32Array(d.data);
805 gl.bindBuffer(gl.ARRAY_BUFFER, vbos[i]);
806 throwError(gl, "bindBuffer");
807 gl.bufferData(gl.ARRAY_BUFFER, d.floatArray, gl.STATIC_DRAW);
808 throwError(gl, "bufferData");
809 }
810 if (this.elementsVBO != null) {
811 var d = this.elements;
812 this.elementsLength = d.data.length;
813 this.elementsType = d.type == gl.UNSIGNED_BYTE ? d.type : gl.UNSIGNED_SH ORT;
814 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.elementsVBO);
815 throwError(gl, "bindBuffer ELEMENT_ARRAY_BUFFER");
816 if (this.elementsType == gl.UNSIGNED_SHORT && !d.ushortArray) {
817 d.ushortArray = new Uint16Array(d.data);
818 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, d.ushortArray, gl.STATIC_DRAW);
819 } else if (this.elementsType == gl.UNSIGNED_BYTE && !d.ubyteArray) {
820 d.ubyteArray = new Uint8Array(d.data);
821 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, d.ubyteArray, gl.STATIC_DRAW);
822 }
823 throwError(gl, "bufferData ELEMENT_ARRAY_BUFFER");
824 }
825 } catch(e) {
826 for (var i=0; i<vbos.length; i++)
827 gl.deleteBuffer(vbos[i]);
828 throw(e);
829 }
830
831 gl.bindBuffer(gl.ARRAY_BUFFER, null);
832 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
833
834 this.length = length;
835 this.vbos = vbos;
836
837 this.initialized = true;
838 },
839
840 use : function() {
841 if (!this.initialized) this.init();
842 var gl = this.gl;
843 for (var i=0; i<arguments.length; i++) {
844 if (arguments[i] == null) continue;
845 gl.bindBuffer(gl.ARRAY_BUFFER, this.vbos[i]);
846 gl.vertexAttribPointer(arguments[i], this.data[i].size, gl.FLOAT, false, 0 , 0);
847 gl.enableVertexAttribArray(arguments[i]);
848 }
849 if (this.elementsVBO != null) {
850 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.elementsVBO);
851 }
852 },
853
854 draw : function() {
855 var args = [];
856 this.use.apply(this, arguments);
857 var gl = this.gl;
858 if (this.elementsVBO != null) {
859 gl.drawElements(gl[this.type], this.elementsLength, this.elementsType, 0);
860 } else {
861 gl.drawArrays(gl[this.type], 0, this.length);
862 }
863 }
864 }
865
866 FBO = function(gl, width, height, use_depth) {
867 this.gl = gl;
868 this.width = width;
869 this.height = height;
870 if (use_depth != null)
871 this.useDepth = use_depth;
872 }
873 FBO.prototype = {
874 initialized : false,
875 useDepth : true,
876 fbo : null,
877 rbo : null,
878 texture : null,
879
880 destroy : function() {
881 if (this.fbo) this.gl.deleteFramebuffer(this.fbo);
882 if (this.rbo) this.gl.deleteRenderbuffer(this.rbo);
883 if (this.texture) this.gl.deleteTexture(this.texture);
884 },
885
886 init : function() {
887 var gl = this.gl;
888 var w = this.width, h = this.height;
889 var fbo = this.fbo != null ? this.fbo : gl.createFramebuffer();
890 var rb;
891
892 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
893 checkError(gl, "FBO.init bindFramebuffer");
894 if (this.useDepth) {
895 rb = this.rbo != null ? this.rbo : gl.createRenderbuffer();
896 gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
897 checkError(gl, "FBO.init bindRenderbuffer");
898 gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, w, h);
899 checkError(gl, "FBO.init renderbufferStorage");
900 }
901
902 var tex = this.texture != null ? this.texture : gl.createTexture();
903 gl.bindTexture(gl.TEXTURE_2D, tex);
904 try {
905 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, w, h, 0, gl.RGBA, gl.UNSIGNED_BYT E, null);
906 } catch (e) { // argh, no null texture support
907 var tmp = this.getTempCanvas(w,h);
908 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, tmp);
909 }
910 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
911 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
912 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
913 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
914 checkError(gl, "FBO.init tex");
915
916 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
917 checkError(gl, "FBO.init bind tex");
918
919 if (this.useDepth) {
920 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERB UFFER, rb);
921 checkError(gl, "FBO.init bind depth buffer");
922 }
923
924 var fbstat = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
925 if (fbstat != gl.FRAMEBUFFER_COMPLETE) {
926 var glv;
927 for (var v in gl) {
928 try { glv = gl[v]; } catch (e) { glv = null; }
929 if (glv == fbstat) { fbstat = v; break; }}
930 log("Framebuffer status: " + fbstat);
931 }
932 checkError(gl, "FBO.init check fbo");
933
934 this.fbo = fbo;
935 this.rbo = rb;
936 this.texture = tex;
937 this.initialized = true;
938 },
939
940 getTempCanvas : function(w, h) {
941 if (!FBO.tempCanvas) {
942 FBO.tempCanvas = document.createElement('canvas');
943 }
944 FBO.tempCanvas.width = w;
945 FBO.tempCanvas.height = h;
946 return FBO.tempCanvas;
947 },
948
949 use : function() {
950 if (!this.initialized) this.init();
951 this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.fbo);
952 }
953 }
954
955 function GLError(err, msg, fileName, lineNumber) {
956 this.message = msg;
957 this.glError = err;
958 }
959
960 GLError.prototype = new Error();
961
962 function makeGLErrorWrapper(gl, fname) {
963 return (function() {
964 try {
965 var rv = gl[fname].apply(gl, arguments);
966 var err = gl.getError();
967 if (err != gl.NO_ERROR) {
968 throw(new GLError(
969 err, "GL error "+getGLErrorAsString(gl, err)+" in "+fname));
970 }
971 return rv;
972 } catch (e) {
973 if (e.glError !== undefined) {
974 throw e;
975 }
976 throw(new Error("Threw " + e.name +
977 " in " + fname + "\n" +
978 e.message + "\n" +
979 arguments.callee.caller));
980 }
981 });
982 }
983
984 function wrapGLContext(gl) {
985 var wrap = {};
986 for (var i in gl) {
987 try {
988 if (typeof gl[i] == 'function') {
989 wrap[i] = makeGLErrorWrapper(gl, i);
990 } else {
991 wrap[i] = gl[i];
992 }
993 } catch (e) {
994 // log("wrapGLContext: Error accessing " + i);
995 }
996 }
997 wrap.getError = function(){ return gl.getError(); };
998 return wrap;
999 }
1000
1001 function getGLContext(canvas) {
1002 return canvas.getContext(GL_CONTEXT_ID, {antialias: false});
1003 }
1004
1005 // Assert that f generates a specific GL error.
1006 function assertGLError(gl, err, name, f) {
1007 if (f == null) { f = name; name = null; }
1008 var r = false;
1009 var glErr = 0;
1010 try { f(); } catch(e) { r=true; glErr = e.glError; }
1011 if (glErr !== err) {
1012 if (glErr === undefined) {
1013 testFailed("assertGLError: UNEXPECTED EXCEPTION", name, f);
1014 } else {
1015 testFailed("assertGLError: expected: " + getGLErrorAsString(gl, err) +
1016 " actual: " + getGLErrorAsString(gl, glErr), name, f);
1017 }
1018 return false;
1019 }
1020 return true;
1021 }
1022
1023 // Assert that f generates some GL error. Used in situations where it's
1024 // ambigious which of multiple possible errors will be generated.
1025 function assertSomeGLError(gl, name, f) {
1026 if (f == null) { f = name; name = null; }
1027 var r = false;
1028 var glErr = 0;
1029 var err = 0;
1030 try { f(); } catch(e) { r=true; glErr = e.glError; }
1031 if (glErr === 0) {
1032 if (glErr === undefined) {
1033 testFailed("assertGLError: UNEXPECTED EXCEPTION", name, f);
1034 } else {
1035 testFailed("assertGLError: expected: " + getGLErrorAsString(gl, err) +
1036 " actual: " + getGLErrorAsString(gl, glErr), name, f);
1037 }
1038 return false;
1039 }
1040 return true;
1041 }
1042
1043 // Assert that f throws an exception but does not generate a GL error.
1044 function assertThrowNoGLError(gl, name, f) {
1045 if (f == null) { f = name; name = null; }
1046 var r = false;
1047 var glErr = undefined;
1048 var exp;
1049 try { f(); } catch(e) { r=true; glErr = e.glError; exp = e;}
1050 if (!r) {
1051 testFailed(
1052 "assertThrowNoGLError: should have thrown exception", name, f);
1053 return false;
1054 } else {
1055 if (glErr !== undefined) {
1056 testFailed(
1057 "assertThrowNoGLError: should be no GL error but generated: " +
1058 getGLErrorAsString(gl, glErr), name, f);
1059 return false;
1060 }
1061 }
1062 testPassed("assertThrowNoGLError", name, f);
1063 return true;
1064 }
1065
1066 Quad = {
1067 vertices : [
1068 -1,-1,0,
1069 1,-1,0,
1070 -1,1,0,
1071 1,-1,0,
1072 1,1,0,
1073 -1,1,0
1074 ],
1075 normals : [
1076 0,0,-1,
1077 0,0,-1,
1078 0,0,-1,
1079 0,0,-1,
1080 0,0,-1,
1081 0,0,-1
1082 ],
1083 texcoords : [
1084 0,0,
1085 1,0,
1086 0,1,
1087 1,0,
1088 1,1,
1089 0,1
1090 ],
1091 indices : [0,1,2,1,5,2],
1092 makeVBO : function(gl) {
1093 return new VBO(gl,
1094 {size:3, data: Quad.vertices},
1095 {size:3, data: Quad.normals},
1096 {size:2, data: Quad.texcoords}
1097 )
1098 },
1099 cache: {},
1100 getCachedVBO : function(gl) {
1101 if (!this.cache[gl])
1102 this.cache[gl] = this.makeVBO(gl);
1103 return this.cache[gl];
1104 }
1105 }
1106 Cube = {
1107 vertices : [ 0.5, -0.5, 0.5, // +X
1108 0.5, -0.5, -0.5,
1109 0.5, 0.5, -0.5,
1110 0.5, 0.5, 0.5,
1111
1112 0.5, 0.5, 0.5, // +Y
1113 0.5, 0.5, -0.5,
1114 -0.5, 0.5, -0.5,
1115 -0.5, 0.5, 0.5,
1116
1117 0.5, 0.5, 0.5, // +Z
1118 -0.5, 0.5, 0.5,
1119 -0.5, -0.5, 0.5,
1120 0.5, -0.5, 0.5,
1121
1122 -0.5, -0.5, 0.5, // -X
1123 -0.5, 0.5, 0.5,
1124 -0.5, 0.5, -0.5,
1125 -0.5, -0.5, -0.5,
1126
1127 -0.5, -0.5, 0.5, // -Y
1128 -0.5, -0.5, -0.5,
1129 0.5, -0.5, -0.5,
1130 0.5, -0.5, 0.5,
1131
1132 -0.5, -0.5, -0.5, // -Z
1133 -0.5, 0.5, -0.5,
1134 0.5, 0.5, -0.5,
1135 0.5, -0.5, -0.5,
1136 ],
1137
1138 normals : [ 1, 0, 0,
1139 1, 0, 0,
1140 1, 0, 0,
1141 1, 0, 0,
1142
1143 0, 1, 0,
1144 0, 1, 0,
1145 0, 1, 0,
1146 0, 1, 0,
1147
1148 0, 0, 1,
1149 0, 0, 1,
1150 0, 0, 1,
1151 0, 0, 1,
1152
1153 -1, 0, 0,
1154 -1, 0, 0,
1155 -1, 0, 0,
1156 -1, 0, 0,
1157
1158 0,-1, 0,
1159 0,-1, 0,
1160 0,-1, 0,
1161 0,-1, 0,
1162
1163 0, 0,-1,
1164 0, 0,-1,
1165 0, 0,-1,
1166 0, 0,-1
1167 ],
1168
1169 indices : [],
1170 create : function(){
1171 for (var i = 0; i < 6; i++) {
1172 Cube.indices.push(i*4 + 0);
1173 Cube.indices.push(i*4 + 1);
1174 Cube.indices.push(i*4 + 3);
1175 Cube.indices.push(i*4 + 1);
1176 Cube.indices.push(i*4 + 2);
1177 Cube.indices.push(i*4 + 3);
1178 }
1179 },
1180
1181 makeVBO : function(gl) {
1182 return new VBO(gl,
1183 {size:3, data: Cube.vertices},
1184 {size:3, data: Cube.normals},
1185 {elements: true, data: Cube.indices}
1186 )
1187 },
1188 cache : {},
1189 getCachedVBO : function(gl) {
1190 if (!this.cache[gl])
1191 this.cache[gl] = this.makeVBO(gl);
1192 return this.cache[gl];
1193 }
1194 }
1195 Cube.create();
1196
1197 Sphere = {
1198 vertices : [],
1199 normals : [],
1200 indices : [],
1201 create : function(){
1202 var r = 0.75;
1203 function vert(theta, phi)
1204 {
1205 var r = 0.75;
1206 var x, y, z, nx, ny, nz;
1207
1208 nx = Math.sin(theta) * Math.cos(phi);
1209 ny = Math.sin(phi);
1210 nz = Math.cos(theta) * Math.cos(phi);
1211 Sphere.normals.push(nx);
1212 Sphere.normals.push(ny);
1213 Sphere.normals.push(nz);
1214
1215 x = r * Math.sin(theta) * Math.cos(phi);
1216 y = r * Math.sin(phi);
1217 z = r * Math.cos(theta) * Math.cos(phi);
1218 Sphere.vertices.push(x);
1219 Sphere.vertices.push(y);
1220 Sphere.vertices.push(z);
1221 }
1222 for (var phi = -Math.PI/2; phi < Math.PI/2; phi += Math.PI/20) {
1223 var phi2 = phi + Math.PI/20;
1224 for (var theta = -Math.PI/2; theta <= Math.PI/2; theta += Math.PI/20) {
1225 vert(theta, phi);
1226 vert(theta, phi2);
1227 }
1228 }
1229 }
1230 }
1231
1232 Sphere.create();
1233
1234 initGL_CONTEXT_ID = function(){
1235 var c = document.createElement('canvas');
1236 var contextNames = ['webgl', 'experimental-webgl'];
1237 GL_CONTEXT_ID = null;
1238 for (var i=0; i<contextNames.length; i++) {
1239 try {
1240 if (c.getContext(contextNames[i])) {
1241 GL_CONTEXT_ID = contextNames[i];
1242 break;
1243 }
1244 } catch (e) {
1245 }
1246 }
1247 if (!GL_CONTEXT_ID) {
1248 log("No WebGL context found. Unable to run tests.");
1249 }
1250 }
1251
1252 initGL_CONTEXT_ID();
OLDNEW
« no previous file with comments | « conformance/more/unit.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698