INTRO TO WEBGL
A crash course in 3D
RENDERING FOR THE AGES
WebGL is how Javascript does 3D.
Comes from OpenGL (Graphics Library).
OpenGL has been around for a while.
Fun fact...
...we're not learning WebGL!
WHAT?! You lied!
3D WebGL is much too complicated.
Ever heard of 15-462?
You need an absurd amount of code.
IT CAN't be that bad...
window.onload = main;
function main() {
var canvas = document.getElementById("canvas");
var gl = getWebGLContext(canvas);
if (!gl) {
return;
}
vertexShader = createShaderFromScriptElement(gl, "2d-vertex-shader");
fragmentShader = createShaderFromScriptElement(gl, "2d-fragment-shader");
program = createProgram(gl, [vertexShader, fragmentShader]);
gl.useProgram(program);
var positionLocation = gl.getAttribLocation(program, "a_position");
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0]), gl.STATIC_DRAW);
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLES, 0, 6);
}
var setupWebGL = function (canvas, opt_attribs) {
function showLink(str) {
var container = canvas.parentNode;
if (container) {
container.innerHTML = makeFailHTML(str);
}
};
if (!window.WebGLRenderingContext) {
showLink(GET_A_WEBGL_BROWSER);
return null;
}
var context = create3DContext(canvas, opt_attribs);
if (!context) {
showLink(OTHER_PROBLEM);
}
return context;
};
var create3DContext = function (canvas, opt_attribs) {
var names = ["webgl", "experimental-webgl"];
var context = null;
for (var ii = 0; ii < names.length; ++ii) {
try {
context = canvas.getContext(names[ii], opt_attribs);
} catch (e) {}
if (context) {
break;
}
}
return context;
}
var updateCSSIfInIFrame = function () {
if (isInIFrame()) {
document.body.className = "iframe";
}
};
var getWebGLContext = function (canvas) {
if (isInIFrame()) {
updateCSSIfInIFrame();
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
} else {
var title = document.getElementsByTagName("title")[0].innerText;
var h1 = document.createElement("h1");
h1.innerText = title;
document.body.insertBefore(h1, document.body.children[0]);
}
var gl = setupWebGL(canvas);
return gl;
};
var loadShader = function (gl, shaderSource, shaderType, opt_errorCallback) {
var errFn = opt_errorCallback || error;
var shader = gl.createShader(shaderType);
gl.shaderSource(shader, shaderSource);
gl.compileShader(shader);
var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
if (!compiled) {
lastError = gl.getShaderInfoLog(shader);
errFn("*** Error compiling shader '" + shader + "':" + lastError);
gl.deleteShader(shader);
return null;
}
return shader;
}
var loadProgram = function (gl, shaders, opt_attribs, opt_locations) {
var program = gl.createProgram();
for (var ii = 0; ii < shaders.length; ++ii) {
gl.attachShader(program, shaders[ii]);
}
if (opt_attribs) {
for (var ii = 0; ii < opt_attribs.length; ++ii) {
gl.bindAttribLocation(program, opt_locations ? opt_locations[ii] : ii, opt_attribs[ii]);
}
}
gl.linkProgram(program);
var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
if (!linked) {
lastError = gl.getProgramInfoLog(program);
error("Error in program linking:" + lastError);
gl.deleteProgram(program);
return null;
}
return program;
};
var createShaderFromScript = function (gl, scriptId, opt_shaderType, opt_errorCallback) {
var shaderSource = "";
var shaderType;
var shaderScript = document.getElementById(scriptId);
if (!shaderScript) {
throw ("*** Error: unknown script element" + scriptId);
}
shaderSource = shaderScript.text;
if (!opt_shaderType) {
if (shaderScript.type == "x-shader/x-vertex") {
shaderType = gl.VERTEX_SHADER;
} else if (shaderScript.type == "x-shader/x-fragment") {
shaderType = gl.FRAGMENT_SHADER;
} else if (shaderType != gl.VERTEX_SHADER && shaderType != gl.FRAGMENT_SHADER) {
throw ("*** Error: unknown shader type");
return null;
}
}
return loadShader(gl, shaderSource, opt_shaderType ? opt_shaderType : shaderType, opt_errorCallback);
};
this.createProgram = loadProgram;
this.createShaderFromScriptElement = createShaderFromScript;
this.getWebGLContext = getWebGLContext;
this.updateCSSIfInIFrame = updateCSSIfInIFrame;
window.requestAnimFrame = (function () {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback, element) {
return window.setTimeout(callback, 1000 / 60);
};
})();
window.cancelRequestAnimFrame = (function () {
return window.cancelCancelRequestAnimationFrame || window.webkitCancelRequestAnimationFrame || window.mozCancelRequestAnimationFrame || window.oCancelRequestAnimationFrame || window.msCancelRequestAnimationFrame || window.clearTimeout;
})();
135 lines of code.
Oh... well then

dimensional confusion
WebGL is actually a 2D library.
Same with OpenGL!

libraries instead
Smart people have thought about this.
That's why we use libraries!
Intro to three.js
A crash course in practical 3D
WHy three.js?
Three.js was a much easier pick.
Everyone uses Three.js!
THREE.js BASICS
Three.js is composed of a scene.
The scene is our 3D space.
Important Three.js terms:
- camera: the player's viewpoint
- controls: handle camera movement
- geometry: a set of vertices
- material: image or shader
- mesh: a geometry + a material
- renderer: scene -> canvas
sample scene
SCENES
var scene = new THREE.Scene();
Scenes are parents--they have children.
Methods/properties that matter:
- scene.add
- scene.remove
- scene.children
- scene.getChildByName
cameras
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000)
Cameras show a slice of 3D space.
They can either be perspective
or orthographic.
Perspective cameras
Perspective is like normal human vision.
Closer things are bigger, farther are smaller.
Orthographic
All objects are perceived as the same size,
regardless of distance.

Camera comparison
Resultrenderers
var renderer = new THREE.WebGLRenderer()
Renderers do the heavy lifting in Three.js.
They translate your 3D space to 2D pixels.
Renderers can also be:
- CanvasRenderer
- CSS3Renderer
- SVGRenderer
- AsciiRenderer
no, really

why webgl?
WebGL uses your graphics card.
GPU >>>>>>>>>>>>>>> CPU
(see: shaders)
geometries
var cubeGeometry = new THREE.CubeGeometry(10, 10, 10);
Geometries are collections of vertices.
Default geometries include:
- Cubes
- Spheres
- Cones
- Toruses
- Knots
sample geometries

materials
var cubeMaterial = new THREE.MeshBasicMaterial({color: 0xff0000});
Materials are the "skins" of objects--
they shade planes between vertices.
Materials can be created/displayed in
a number of different ways.
materialist
- MeshBasicMaterial: flat color
- MeshDepthMaterial: color by distance
- MeshNormalMaterial: color by face vector normal
- MeshFaceMaterial: different material per face
- MeshLambertMaterial: diffuse lighting
- MeshPhongMaterial: shiny lighting
- ShaderMaterial: h4x material in C
Meshes
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
Mesh = geometry + material
Also has useful properties:
- Scale
- Rotation
- Position
what's missing?
Number of common things missing:
- Render loop
- Lighting
- Skybox
- Camera controls
- Particles
and now it's time
To dive into the code.
Week 8
By Will Crichton
Week 8
- 1,153
