| CPSC 424 | Computer Graphics | Fall 2025 |
three.js provides a high-level scene graph for designing WebGL scenes. This is the second of two labs using three.js. It deals with features of three.js that support more sophisticated scenes and effects: ways of building mesh objects, cubemaps, skyboxes, reflection, refraction, shadows, and (optionally) bump maps, dynamic cubemaps, and/or custom shaders.
Successful completion of this lab means that you can use three.js to:
This is an individual lab. You may get technical help from others, but the effort and ideas that go into producing solutions should be yours.
You may use AI as outlined in
the Use of AI policy —
Copilot's inline coding suggestions, explain, fix, review and
comment features but not code generation from English prompts.
Also:
Hand in your work by copying your ~/cs424/lab9 folder into your handin folder (/classes/cs424/handin/username, where username is your username).
Check that the result is that your files are contained in /classes/cs424/handin/username/lab9 — if not, fix it!
Copy the directory /classes/cs424/lab9 and its contents into your ~/cs424/workspace directory. You should end up with a folder lab9 inside your workspace directory, with files inside of it.
If you haven't previously copied /classes/cs424/cubemap-textures and its contents into your ~/cs424/workspace directory, do that now. Make sure that you end up several folders (each containing the six images making up a cubemap) inside a folder cubemap-textures which is directly contained within workspace.
Make sure that all of the directories are named exactly as specified and end up at the same (top) level in your workspace directory. This is important so that the relative path names used to access common files remain the same so your program doesn't break when you hand it in.
lab9.html is a template for a three.js program.
Your best reference sources are the slides from class (which pull out and organize the key points), the examples from class (which put all the pieces together), and the textbook. Chapter 5 covers three.js.
You will need a PerspectiveCamera when using a skybox. Increase the field of view angle (up to 90 degrees) to see more of the background.
Environment mapping is used for both reflection and refraction, but different settings are required depending on how the cubemap is being used. While you want to use the same image(s) for the reflection cubemap, refraction cubemap, and skybox, you do not need to use the same JavaScript object.
MeshBasicMaterial is used in the examples of reflection and refraction from class because there is no additional lighting in those scenes — the skybox provides sufficient "light". The material properties for reflection and refraction aren't limited to MeshBasicMaterials, however, and you can (will need to) use other material types in order to see the effects of light sources (both illumination and shadows).
JavaScript has the constant Math.PI for π. Trigonometric functions like sin and cos are Math.sin and Math.cos.
trefoil knot surface
x = r sin(6πu) / (2 + cos(2πv))
y = r (sin(2πu) + 2 sin(4πu)) / (2 + cos(2πv + 2π/3))
z = ( r/2 (cos(2πu) - 2 cos(4πu)) (2 + cos(2πv)) (2 + cos(2πv + 2π/3)) ) / 4
x = sin(2πt) + 2 sin(4πt)
y = cos(2πt) - 2 cos(4πt)
z = -sin(6πt)
parabola
x = t
y = t2
cycloid (try changing the 2 to higher multiples of 2)
x = 2πt - sin(2πt)
y = 1 - cos(2πt)
various hypotrochoids (also see the "see also" links) — you'll generally need to scale the parameter by 2π or a larger multiple to get the whole curve with a parameter range 0-1
Use the provided lab9.html as the starting point for this lab. This is the same skeleton provided for lab 8 — it sets up the structure for a three.js program with a trackball rotator (so the mouse can spin the camera around) as discussed in class. Note that running the program will result in a blank page and an error message in the console until a scene and camera have been created. (After that you should at least see a dark gray canvas.)
Create a scene of your own design which showcases some of the more advanced objects, lighting, and materials supported by three.js. For full credit, your scene must meet the requirements (both general and specific) below.
General requirements:
Depict something recognizable rather than just a bunch of shapes. It's fine to simplify representations, like was done when creating a tree from a cone and a cylinder. Shapes should be positioned deliberately.
Create an original scene — you can't just copy elements from examples in the book or class. (If you want to use the same kinds of elements, such as a tree or a car, they need to be significantly redesigned.) It is OK to build on your scene from lab 8, but the requirements for this lab must be met through new additions to the scene.
Use elements appropriately e.g. only use a faceted material on something that is supposed to be polyhedral, don't over- or under-light the scene, only apply modeling transforms that have a visible effect (e.g. there's no point in rotating a sphere, rotating by a multiple of 360 degrees, or a uniform scale by 1), etc.
Specific requirements:
Include at least one light which provides illumination for the scene.
Include at least eight mesh objects, one of which acts as a stage (or platform or ground) that the other objects sit on or above. Demonstrate each of the ways to build mesh objects:
Some possibilities for parametric surfaces and curves are given above, but feel free to use other equations (cite a source), modify the ones given, or make up your own. The originality requirement for the scene means that you can't just copy code from examples in the slides or textbook, though.
Include at least two reflective objects. They should have different materials, at least one of which combines a color and/or an image texture with the reflection.
Include at least two refractive objects. They should have different materials, at least one of which combines a color and/or an image texture with the transparency.
Non-transparent objects should cast shadows. This also means that objects and light(s) should be positioned so that there is ample opportunity to observe shadows. There should be at least one instance of shadows falling on a reflective or refractive object.
Ideally, position elements so that it isn't obvious that the reflections and transparency don't include the other objects in the scene, though this isn't required. Optionally (extra credit), explore and use a CubeCamera to generate a dynamic cubemap for the skybox to address some of these limitations. CubeCamera is mentioned in section 5.3.5 and the API includes a code example to help get you started.
Other extra credit options include bump mapping (not covered in the slides or the textbook, but there is an example posted) and custom shaders (in the slides plus posted examples). Try implementing non-photorealistic rendering like Gooch or cel shading!