← Back to Archive

Graphics Programming with Three.js and WebGL

Three.js WebGL CPSC 314 Projects
Graphics Programming Cover

A series of graphics projects that utilizes the power of three.js Javascript 3D library.

Course Overview

The projects are completed during CPSC 314 in UBC. Template codes are provided by Mikhail Bessmeltsev. This course provides an introduction into the basic components of computer graphics including the mathematics and physics for computer graphics, foundations of 3D rendering, image processing and rendering pipeline.


Project 1: Animated Armadillo

Animated Armadillo

The template provides a simple scene with a yellowish 3D display, working normally and displaying an armadillo, and a non-functioning red remote control. The variable remotePosition is changed using arrow keys and passed to the remote control shader (remote.vs.glsl) using uniform variables in response to keyboard input.

The remote control's fragment shader (remote.fs.glsl) is modified so that it changes its color according to a uniform variable tvChannel. You are able to switch channels using your keyboard (keys 1-3) and see the remote react. The fragments that are within some distance of the remote changes color due to the modification to the character's shaders. The armadillo is distorted in different ways for different channels including deforming the vertices in the armadillo in a wave over time and exploding the model along face normals.


Project 2: Ostrich with Transformation

Ostrich with Transformation

The template provides a torso (placed with respect to the world coordinate frame), a neck (placed with respect to the torso coordinate frame) and a head (placed with respect to the neck coordinate frame) of the ostrich leaving the legs to be completed.

The legs I added consist of two parts, both of which are cylinders: a thigh (placed with respect to the torso coordinate frame) and a lower leg (placed with respect to the thigh coordinate frame). The thigh and lower leg coordinate frames are rotated so that they move like the ostrich is running. The lower leg not only moves with respect to the thigh, but also has an independent motion. The running animation is cyclical and continues to move back and forth. They are moving at a reasonable speed. A timer is used to keep animation speed consistent instead of animating the legs every frame. Five different poses for the static body coordinate frames are added. Pressing the number keys between 0 and 5 should each show a different pose.


Project 3: Shading, Lighting and Textures

Shading and Lighting

This project demonstrates couple of common shading methods including Gouraud Shading, Phong Reflection and Phong Shading, Blinn-Phong Shading and some basic texturing. The lightColor, lightDirection and ambientColor variables are defined as well as material properties for the objects (defined in kSpecular, kDiffuse and kAmbient).

Gouraud shading calculates the lighting of an object at each vertex (e.g. in the vertex shader). The standard graphics pipeline will then interpolate the color of the object between the vertices to get the individual fragment colors. The Phong reflection model is achieved by passing the lighting parameters (such as the triangle normal and vertex position) as varying variables to the fragment shader. Then calculate the lighting of the mesh at each fragment using the interpolated lighting parameters. This allows the shading model to better approximate curved surfaces and produces a very smooth shading model.

Blinn-Phong Shading is achieved by computing the dot product between the halfway vector between light and viewing direction, and the surface normal. In the texturing part, UV coordinates are taken from the vertex buffer (three.js provides them for free on default objects such as the sphere in our assignment). UV coordinates are a 2D index into an image file whose RGB values can be used to help color the mesh.


Project 4: Ray Tracing

Ray Tracing

The first step to implement ray tracing is the basic ray casting for all pixels in the image, using the camera location and the coordinates of each pixel. Then iteratively test all the object's intersection with the given ray and update the depth as the first intersection's depth. The functions of intersection tests and the functions of casting primary rays are implemented in regard to different geometries to test if a ray intersects the objects.

Next step is local illumination. It's achieved by calculating the ambient, diffuse, and specular terms in order to determine the color at the point where the ray intersects the scene. Then to implement the shadow ray calculation and update the lighting computation accordingly, shadow ray is emitted from a point to compute direct illumination to determine which lights are contributing to the lighting at that point.

Finally to implement the secondary ray recursion for reflection, the rayDepth recursion depth variable is used to stop the recursion process and update the lighting computation at each step to account for the secondary component.

Tools & Technologies

JavaScript GLSL Three.js WebGL C++ Linear Algebra Computer Graphics