webgl patrick cozzi university of pennsylvania cis 565 - fall 2012
TRANSCRIPT
![Page 1: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/1.jpg)
WebGL
Patrick CozziUniversity of PennsylvaniaCIS 565 - Fall 2012
![Page 2: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/2.jpg)
The web has text, images, and videoWhat is the next media-type?
We want to supportWindows, Linux, MacDesktop and mobile
WebGL
2
![Page 3: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/3.jpg)
Bring 3D to the Masses
Put it in on a webpageDoes not require a plugin or installDoes not require administrator rights
Make it run on most GPUs
3
![Page 4: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/4.jpg)
WebGL
Image from http://www.khronos.org/assets/uploads/developers/library/2011-siggraph-mobile/Khronos-and-the-Mobile-Ecosystem_Aug-11.pdf
OpenGL ES 2.0 for JavaScriptSeriously, JavaScript
4
![Page 5: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/5.jpg)
WebGL Includes
Vertex shadersFragment shadersVertex buffersTexturesFramebuffersRender states…
Does not includeGeometry shadersTessellation shadersVertex Array ObjectsMultiple render targetsFloating-point texturesCompressed texturesFS depth writes…
See http://www.khronos.org/registry/webgl/specs/latest/5
![Page 6: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/6.jpg)
WebGL
If you know OpenGL, you already know WebGL If you know C++, the real learning curve is
JavaScript
6
![Page 7: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/7.jpg)
WebGL Alternatives?
Flash Silverlight Java Applets Unity
7
![Page 8: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/8.jpg)
WebGL
Creating a context is easy:
// HTML:<canvas id="glCanvas" width="1024" height="768"></canvas>
// JavaScript:var gl = document.getElementById("glCanvas").getContext("experimental-webgl");
8
![Page 9: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/9.jpg)
WebGL
The rest is similar to desktop OpenGL:
// ...gl.bindBuffer(/* ... */);gl.vertexAttribPointer(/* ... */);gl.useProgram(/* ... */);gl.drawArrays(/* ... */);
Checkout http://learningwebgl.com/9
![Page 10: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/10.jpg)
WebGL
Create an animation loop:
(function tick(){ // ... GL calls to draw scene window.requestAnimationFrame(tick);})();
You want this to work cross-browser. See http://paulirish.com/2011/requestanimationframe-for-smart-animating/10
![Page 11: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/11.jpg)
WebGL Performance
Performance can be very good. Why?
11
![Page 12: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/12.jpg)
WebGL Performance
Performance can be very good. Why?The GPU is still doing the renderingBatch!
Draw multiple objects with one draw call Sort by texture Push work into shaders Push work into web workers
See http://www.youtube.com/watch?v=rfQ8rKGTVlg12
![Page 13: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/13.jpg)
WebGL Performance
Image from http://openglinsights.com/
32x32 64x64 128x128
C++ 1.9 ms 6.25 ms 58.82 ms
Chrome 18 27.77 ms 111.11 ms 454.54 ms
x slowdown 14.62 17.78 7.73
32x32 64x64 128x128
C++ 3.33 ms 9.43 ms 37.03 ms
Chrome 18 12.82 ms 22.72 ms 41.66 ms
x slowdown 3.85 2.41 1.13
CPU-intensive
GPU-intensive (256 draws per frame)13
![Page 14: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/14.jpg)
WebGL and other APIs
Take advantage of other web APIs:HTML5 <video>2D <canvas>CSS transformsComposite UI elementsWeb workersTyped Arrays
14
![Page 15: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/15.jpg)
HTML5 on Mobile
Touch eventsTest with http://www.snappymaria.com/misc/TouchEventTest_v2.html
Geolocation Device orientation and motion
The future of HTML5 and WebGL on mobile is very promising
15
![Page 16: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/16.jpg)
WebGL support is good, and it is getting
better…
16
![Page 18: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/18.jpg)
Desktop WebGL Support
In October, 2012
- 3rd Party Plugins available
See http://www.khronos.org/webgl/wiki/Getting_a_WebGL_Implementation18
![Page 19: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/19.jpg)
Android WebGL Support
In October, 2012
Stock Browser• Demo at SIGGRAPH 2011
For Cesium, see our mobile page
19
![Page 20: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/20.jpg)
Mobile WebGL Support
In October, 2012
See http://news.cnet.com/8301-30685_3-20071902-264/apple-signs-up-for-webgl-graphics-in-iads/
In iOS 5 for iAd developers
20
![Page 21: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/21.jpg)
WebGL on Your System
http://www.webglreport.com
21
![Page 22: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/22.jpg)
Desktop WebGL Support
WindowsNo OpenGL driver installed? Old driver?
Only 35% of Windows XP machines have GL 2 driversBuggy driver?No problem:
ANGLE – Almost Native Graphics Layer Engine
OpenGL ES 2.0
Direct3D 9
See http://code.google.com/p/angleproject/22
![Page 23: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/23.jpg)
N-Body Simulationhttp://www.youtube.com/watch?v=F7YSQxz3j7o
http://www.khronos.org/webcl/Prototypes for Firefox and WebKit are available
WebCL OpenCL bindings for JavaScript are
coming.
23
![Page 24: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/24.jpg)
Browser Architecture
Single Process
See http://www.khronos.org/assets/uploads/developers/library/2010_siggraph_bof_webgl/WebGL-BOF-2-WebGL-in-Chrome_SIGGRAPH-Jul29.pdf24
![Page 25: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/25.jpg)
Browser Architecture
Chrome’s Multi-process
See http://www.khronos.org/assets/uploads/developers/library/2010_siggraph_bof_webgl/WebGL-BOF-2-WebGL-in-Chrome_SIGGRAPH-Jul29.pdf25
![Page 26: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/26.jpg)
Browser Architecture
Chrome’s Multi-process
See http://www.khronos.org/assets/uploads/developers/library/2010_siggraph_bof_webgl/WebGL-BOF-2-WebGL-in-Chrome_SIGGRAPH-Jul29.pdf26
![Page 27: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/27.jpg)
Browser Architecture
Chrome’s Multi-process
See http://www.khronos.org/assets/uploads/developers/library/2010_siggraph_bof_webgl/WebGL-BOF-2-WebGL-in-Chrome_SIGGRAPH-Jul29.pdf27
![Page 28: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/28.jpg)
Questions
In a multi-process is gl.Get* slow? Why?
What about security?
28
![Page 29: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/29.jpg)
Cross-Origin Resource Sharing
Images can’t always be used as texture sources. Why?
29
![Page 30: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/30.jpg)
Cross-Origin Resource Sharing
var img = new Image();img.onload = function() { gl.texImage2D(/* ... */, img);};img.src = "image.png";
Same domain is OK:
30
![Page 31: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/31.jpg)
Cross-Origin Resource Sharing
var img = new Image();img.onload = function() { gl.texImage2D(/* ... */, img);};img.crossOrigin = "anonymous";img.src ="http://another-domain.com/image.png";
Another domain requires CORS if supported:
31
![Page 32: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/32.jpg)
Cross-Origin Resource Sharing
Not all servers support CORS:
Browser
www.your-domain.com www.another-domain.com
html/js/cssfiles
Images filesused for textures
32
![Page 33: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/33.jpg)
Cross-Origin Resource Sharing
Use a proxy server:
Browser
www.your-domain.com
www.another-domain.com
html/js/cssfiles
Images filesused for textures
Images filesused for textures
“proxy.php?http://another-domain.com/image.png"
See http://resources.esri.com/help/9.3/arcgisserver/apis/javascript/arcgis/help/jshelp/ags_proxy.htm33
![Page 34: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/34.jpg)
Denial of Service Attacks
Long draw callsComplicated shadersBig vertex buffers
SolutionsKill long draw callsForbid further rendering
Lots of WebGL security info: http://learningwebgl.com/blog/?p=389034
![Page 35: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/35.jpg)
WebGL Libraries
Three.js: https://github.com/mrdoob/three.js/
Cesium: http://cesium.agi.com/
Many more: http://www.khronos.org/webgl/wiki/User_Contributions
35
![Page 36: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/36.jpg)
WebGL Resources
WebGL Camps: http://www.webglcamp.com
Learning WebGL: http://learningwebgl.com
36
![Page 37: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/37.jpg)
The Joys of JavaScript
Skip the next 30 slides if you already know JavaScript37
![Page 38: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/38.jpg)
JavaScript is weakly typed…
38
![Page 39: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/39.jpg)
JavaScript Type System
short, int, float, double. Who needs them?
var n = 1;
39
![Page 40: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/40.jpg)
JavaScript Type System
JavaScript has numbers, strings, and booleans:
var n = 1;var s = “WebGL”;var b = true;
40
![Page 41: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/41.jpg)
JavaScript Type System
This compiles:
var n = 1;var s = “WebGL”;var b = true;
var sum = n + s + b;
41
![Page 42: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/42.jpg)
JavaScript is a functional language…
42
![Page 43: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/43.jpg)
JavaScript Functions
Looks familiar:
Functions are first-class objects, so…
function add(x, y) { return x + y;}
var sum = add(1, 2);
43
![Page 44: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/44.jpg)
JavaScript Functions
Functions are objects:
var add = function(x, y) { return x + y;};
var sum = add(1, 2);
44
![Page 45: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/45.jpg)
JavaScript Functions
Pass functions to functions:
var add = function // ...
function execute(op, x, y) { return op(x, y);}
var sum = execute(add, 1, 2);45
![Page 46: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/46.jpg)
JavaScript Anonymous Functions
Why name functions?
function execute(op, x, y) // ...
var sum = execute(function(x, y) { return x + y;}, 1, 2);
46
![Page 47: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/47.jpg)
JavaScript Closures
Why limit scope?
var z = 3;
var sum = execute(function(x, y) { return x + y + z;}, 1, 2);
47
![Page 48: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/48.jpg)
JavaScript is a dynamic language…
48
![Page 49: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/49.jpg)
JavaScript Object Literals
Who needs struct? Create objects on the fly:
var position = { x : 1.0, y : 2.0};
49
![Page 50: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/50.jpg)
JavaScript Object Literals
Why not add fields on the fly too?
var position = { x : 1.0, y : 2.0};position.z = 3.0;
50
![Page 51: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/51.jpg)
JavaScript Object Literals
Who needs class?
51
![Page 52: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/52.jpg)
JavaScript Object Literals
Who needs class? Create functions too:
var position = { x : 1.0, y : 2.0, min : function() { return Math.min(this.x, this.y); }};
52
![Page 53: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/53.jpg)
JavaScript Object Literals
Why not change min()?
position.z = 3.0;position.min = function() { return Math.min(this.x, this.y, this.z);};
53
![Page 54: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/54.jpg)
JavaScript Object Literals
Useful for passing to functions. Why?
54
![Page 55: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/55.jpg)
JavaScript Object Literals
Useful for passing to functions. Why? What do these arguments mean?
pick(322, 40, 5, 4);
55
![Page 56: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/56.jpg)
JavaScript Object Literals
Useful for passing to functions. Why? What do these arguments mean?
pick({ x : 322, y : 40, width : 5, height : 4});
56
![Page 57: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/57.jpg)
JavaScript does object-oriented…
57
![Page 58: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/58.jpg)
JavaScript Constructor Functions
function Vector(x, y) { this.x = x; this.y = y;}
var v = new Vector(1, 2);
58
![Page 59: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/59.jpg)
JavaScript Constructor Functions
function Vector(x, y) { this.x = x; this.y = y; this.min = function() { return Math.min(this.x, this.y); };}
Objects can have functions:
59
![Page 60: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/60.jpg)
JavaScript Constructor Functions
function Vector(x, y) { this.x = x; this.y = y;}
Vector.prototype.min = function() { return Math.min(this.x, this.y);};
Objects have prototypes:
60
![Page 61: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/61.jpg)
JavaScript Polymorphism
No need for virtual functions
function draw(model) { model.setRenderState(); model.render();}
61
![Page 62: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/62.jpg)
JavaScript Polymorphism
No need for virtual functions
var level = { setRenderState : function() // ... render : function() // ...};
draw(level); // Just works
62
![Page 63: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/63.jpg)
JavaScript Build Pipeline
See http://www.julienlecomte.net/blog/2007/09/16/
Concatenate Minify
Different than C++ Goal: fast downloads Common:
Alternative: fine-grain modules How do you deploy shaders?
.jsfiles
One .js file
“Compressed” .js file
63
![Page 64: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/64.jpg)
JavaScript Advice
Use JSHint Have excellent test coverage Use the Chrome and Firefox debuggers
64
![Page 65: WebGL Patrick Cozzi University of Pennsylvania CIS 565 - Fall 2012](https://reader035.vdocuments.site/reader035/viewer/2022062408/56649ede5503460f94bef221/html5/thumbnails/65.jpg)
JavaScript Resources
I promise I do not work for O'Reilly or Yahoo65