hacking with
THREE.js & WebGL
three.js
is awesome
... but has some pitfalls
BLOATED
- 430kb minified
- More features daily
- Not very modular
“locked” to scene graph
- Lots of stuff going on behind the scenes
- sorting geometry
- new shaders being created
- shader uniform updates
- CPU => GPU uploads
DYNAMIC RENDERING
- Buffering geometry every frame
- text effects on Jam3 site
- complex 2D games
- animated 2D shapes
- complex GUIs, text
TEXT RENDERING
-
Only supports mesh-based text
-
Limited unicode sets, i.e. no icon fonts
-
Uses typeface.js - no kerning or glyph metrics
-
No control over triangulation
-
Triangulation errors e.g. Jam3 Site
-
Curves look segmented at large sizes
-
Large JS file for a font
-
Expensive to process and render
-
Overkill for simple 2D needs
TEXT ALTERNATIVES
-
Custom triangulation, e.g. poly2tri
-
Custom TTF-to-JSON tools
-
Bitmap Fonts
-
Signed Distance Field Fonts:
http://bit.ly/1gvA3CH -
CPU Vector Fonts:
http://jabtunes.com/labs/3d/vector/ -
GPU Vector Fonts:
https://code.google.com/p/glyphy/ -
Server-side FreeType rendering
-
Client-side FreeType rendering (Emscripten)
fontpath
-
more control over triangulation
-
kerning, advanced glyph metrics
-
more focus on 2D and 3D effects
-
not tied to any particular renderer
performance optimizations
SNAPPY WEBGL apps
- Single WebGL context/canvas
- Load textures/geometry/etc once and re-use it
- failIfMajorPerformanceCaveat
- Don't abuse requestAnimationFrame
- Keep an eye on memory in Chrome debugger
- Debug GL state to see what textures and
shaders are being created - Beware of "GPU sync" ...
GPU SYNC
Moving a texture from <img> into GPU memory
- Synchronous, causes a pipeline stall
- Upwards of a couple seconds
- Makes CSS/DOM animations stutter
- THREE.js gives us no control when it happens
- Happens with buffers, too (i.e. models)
GENERAL WebGL OPTIMIZATIONS
-
batch everything
-
be careful with render-to-texture
-
and FBO switches, e.g. post-processing
-
re-use shaders & merge shader code
-
use sprite sheets (for 2D games, PIXI, etc)
-
prefer vertex over fragment operations
-
simplify shaders: avoid "branching"
-
{ alpha: false }
-
{ antialias: false }
example:
vertex animations
-
First thought: Modify vertex positions
-
This leads to re-uploading vertex buffers to GPU
-
Different meshes can no longer share
the same geometry - Solution: move the animation to the vertex shader
- Custom vertex shader with THREE.js' default
Lambert fragment shader:
http://bit.ly/1oe42lZ
“KAMI”
DOWN TO THE METAL
-
Lightweight
-
Full control over GL state
-
Compressed textures
-
SpriteBatching
-
Good for learning what happens "under the hood"
gl-modules
- run.south.im uses it
-
Very modular
- Many small components
- composes well with ndarray
cheers.
Hacking with THREE.js
By Matt DesLauriers
Hacking with THREE.js
- 7,827