|
Notes for April 8 class -- Building on three.js
Using a higher level library
Now that you have seen how to directly interface with WebGL,
we can move on and use a higher level library.
three.js is an open source
library that builds an infrastructure of modeling
and rendering tools upon the base level of WebGL.
It allows you to more rapidly create larger projects,
without forcing you to deal with many of the low
level details.
When you need to, it also gives you ways to directly
access WebGL directly, which you might want to
do if you choose to write your own shaders
or create your own custom 3D shapes.
|
Making simple scenes
The html file you are reading contains the following declaration:
<script src=three.js></script>
Three.js is very powerful and general, but
while you are getting to know it,
it can be good to start with simple things.
NOTE: There are different versions of the three.js source file.
For stability in your assignments, please unzip and use
the files referred to below in the homework assignment.
I have created some support code to make it easier for you to make simple example scenes:
window.time = 0;
window.SimpleScene = function() {
this.init = function(name) {
this.scene = new THREE.Scene();
// CREATE THE CAMERA, AND ATTACH IT TO THE SCENE.
var camera = new THREE.PerspectiveCamera(50, 1, 1, 10000);
camera.position.z = 5;
this.scene.add(camera);
// CREATE THE WEBGL RENDERER, AND ATTACH IT TO THE DOCUMENT BODY.
var renderer = new THREE.WebGLRenderer( { alpha: true } );
renderer.setSize(400, 400);
document.getElementById(name).appendChild(renderer.domElement);
// CALL THE USER'S SETUP FUNCTION JUST ONCE.
this.setup();
// START THE ANIMATION LOOP.
var that = this;
(function tick() {
time = (new Date().getTime()) / 1000;
that.update();
renderer.render(that.scene, camera);
requestAnimationFrame(tick);
})();
}
};
|
A very simple example
Given the above support,
the code shown in the left column of the below 2×1 table, when placed within a <script>
tag
and a
</script>
tag,
produces the simple animated scene shown in the right column of the table.
The HTML code I used for the right column of the below table is:
<td id='Scene1_id'></td>
function Scene1() {
var box;
this.setup = function() {
var geometry = new THREE.BoxGeometry(2, 2, 2);
var material = new THREE.MeshNormalMaterial();
box = new THREE.Mesh(geometry, material);
this.scene.add(box);
}
this.update = function() {
box.rotation.x += 0.01;
box.rotation.y += 0.02;
}
}
Scene1.prototype = new SimpleScene;
new Scene1().init('Scene1_id');
|
|
|
Creating a jointed hierarchy
Here we are creating an object hierarchy,
using an invisible intermediate joint to help
create an animation of a ball rolling around in a circular path atop a box:
-
The invisible joint, which is a child of the box, rotates about the y axis.
-
The ball, which is a child of the invisible joint, spins in place about the x axis, at position (1,0,0).
The combined movements of the joint and the ball create the desired animation.
function Scene2() {
var box, joint, ball;
this.setup = function() {
var light = new THREE.DirectionalLight(0xffffff);
light.position.set(1,1,1).normalize();
this.scene.add(light);
var material = new THREE.MeshNormalMaterial();
box = new THREE.Mesh(new THREE.BoxGeometry(2, 2, 2), material);
joint = new THREE.Mesh();
ball = new THREE.Mesh(new THREE.SphereGeometry(1, 16, 16), material);
this.scene.add(box);
box.add(joint);
joint.add(ball);
}
this.update = function() {
box.rotation.x = .5;
joint.position.y = 1.5;
joint.rotation.y = time;
ball.position.set(1,0,0);
ball.rotation.x = -time;
ball.rotation.z = Math.PI/2;
ball.scale.set(.5,.5,.5);
}
}
Scene2.prototype = new SimpleScene;
new Scene2().init('Scene2_id');
|
|
|
Using a pre-defined three.js material
Here is an example of using a material based on a Phong shader
that has been written for you by three.js.
When using a pre-defined material,
all you need to do is provide the shader parameters.
function Scene3() {
var light, ball;
this.setup = function() {
light = new THREE.DirectionalLight(0xffffff);
light.position.set(1,1,1).normalize();
this.scene.add(light);
var ballGeometry = new THREE.SphereGeometry(1, 16, 16);
var ballMaterial = new THREE.MeshPhongMaterial({
ambient : 0,
emissive : 0x800000,
color : 0x800000,
specular : 0x101010,
shininess: 40
});
ball = new THREE.Mesh(ballGeometry, ballMaterial);
ball.material.shading = THREE.SmoothShading;
this.scene.add(ball);
}
this.update = function() {
light.position.set(Math.sin(10 * time), 1, 1).normalize();
}
}
Scene3.prototype = new SimpleScene;
new Scene3().init('Scene3_id');
|
|
|
Defining your own vertex and fragment shaders
Three.js will also let you define your own custom materials,
by specifying your own vertex and fragment shaders.
THe three.js library will then compile these for you, and
incorporate them into the scene like any other materials.
Below is the simple example we created in class.
function Scene4() {
var myVertexShader = [
,'varying vec3 vPosition;'
,'varying vec3 vNormal;'
,'void main() {'
,' vPosition = position;'
,' vNormal = normal;'
,' gl_Position = projectionMatrix * modelViewMatrix * '
,' vec4( position + vec3(0.,.1,.1) * '
,' sin(10. * position.x), 1.);'
,'}'
].join('\n');
var myFragmentShader = [
,'varying vec3 vPosition;'
,'varying vec3 vNormal;'
,'void main() {'
,' float c = .5 + .3 * (vNormal.x + vNormal.y + vNormal.z);'
,' gl_FragColor = vec4(c, c, c*.5, 1.);'
,'}'
].join('\n');
var fred;
this.setup = function() {
var light = new THREE.DirectionalLight(0xffffff);
light.position.set(1,1,1).normalize();
this.scene.add(light);
var material = new THREE.Material();
material.vertexShader = myVertexShader;
material.fragmentShader = myFragmentShader;
material.shading = THREE.SmoothShading;
fred = new THREE.Mesh(new THREE.SphereGeometry(1,32,16), material);
this.scene.add(fred);
}
this.update = function() {
fred.rotation.x += 0.01;
fred.rotation.y += 0.01;
}
}
Scene4.prototype = new SimpleScene;
new Scene4().init('Scene4_id');
|
|
|
A tour through the cool three.js examples
We looked at some of the cooler examples on the three.js front page:
threejs.org
Then we looked at some of the many tutorial examples on their examples page:
threejs.org/examples
I encourage you to look through those pages for yourself, and
spend some time just exploring.
|
Homework, due by start of class on Wednesday April 15
-
Start out by unzipping this copy of these course notes.
You will build your assignment by modifying index.html in that unzipped folder.
-
Make something cool and fun using three.js.
Feel free to build on top of the code that I have
already provided.
But please do not simply create something very close
to the examples on this page.
You should only use the examples on this page
as a starting point to create your own original work.
-
Extra credit:
Find something that inspires you in the three.js examples,
and create something original based on that.
Don't simply copy their example with minor variations.
As always, you get extra points for making something that is fun, exciting, beautiful or original.
|
| |