PROGRAMMING ASSIGNMENT – UNIT 3
Transformations, Color, and Animation in Computer Graphics
Course: CS 4406-01 – Computer Graphics
Unit: 3
INTRODUCTION
Computer graphics systems rely on geometric modeling, transformations, lighting, and
color theory to produce visually realistic scenes. In this assignment, I implemented a 3-
dimensional animated object using the [Link] WebGL library to demonstrate practical
understanding of object transformations, dynamic color manipulation, lighting effects,
and collision-based animation.
The program creates a 3D sphere that moves within the viewing area and simulates a
bouncing motion. Each time the object reaches the boundary of the viewport and changes
direction, its color changes. Additionally, the scene includes a fixed light-yellow
directional light positioned in the upper-left corner to demonstrate shading and shadow
variation as the object moves. This implementation reflects core principles of computer
graphics modeling and rendering pipelines (Akenine-Möller et al., 2018).
Scene Construction and Graphics Pipeline
A [Link] scene was created to serve as the rendering container. In real-time graphics
systems, a scene represents a structured collection of objects, lights, and cameras that are
processed by the rendering pipeline (Shirley et al., 2020).
Camera Selection
An Orthographic Camera was used rather than a Perspective Camera. Orthographic
projection removes depth scaling distortion, making viewport boundary detection more
predictable for collision logic. Projection transformations are fundamental in converting
3D coordinates into 2D display space (Akenine-Möller et al., 2018).
The camera frustum dimensions were configured so that the sphere occupies only a small
portion of the viewing area, satisfying the assignment requirement.
Renderer Configuration
A WebGL renderer with anti-aliasing enabled was used to ensure smooth edge rendering.
Shadow mapping was activated to allow visible light and shadow interaction between
objects in the scene. Shadow mapping is a common real-time technique used to simulate
light occlusion (Shirley et al., 2020).
3D Object Creation and Scaling
A sphere geometry ([Link]) was selected as the 3D object. The radius
was deliberately kept small relative to the camera frustum so that it covers only a limited
area of the viewport.
The sphere uses MeshStandardMaterial, which supports physically based lighting
calculations. Materials in graphics determine how surfaces respond to illumination,
affecting color, reflectivity, and shading (Akenine-Möller et al., 2018).
The object was configured to:
Cast shadows
Respond to directional lighting
Change color dynamically
Lighting Implementation
Lighting is essential in revealing shape, depth, and surface orientation in 3D graphics
(Shirley et al., 2020). A directional light source was implemented with the color
#FFFFAA (light yellow) to meet the assignment requirement.
The light was positioned in the upper-left region of the scene using negative x and
positive y coordinates. Because directional light simulates a distant source (such as
sunlight), it produces consistent light rays across the scene.
Shadow casting was enabled on both the light and the sphere. A ground plane was added
to receive shadows, allowing dynamic shadow movement as the sphere changes position.
An ambient light source was added at low intensity to prevent shadows from appearing
completely black, improving visual realism.
Transformations and Animation
Object transformations in computer graphics typically include translation, rotation, and
scaling (Akenine-Möller et al., 2018). In this assignment, translation transformations
were applied by modifying:
[Link].x
[Link].y
The animation loop was implemented using requestAnimationFrame(), which allows
continuous frame updates synchronized with browser refresh cycles.
Velocity variables (vx, vy) were used to increment position values each frame, creating
smooth motion across the viewport.
Bounce Logic and Collision Detection
Collision detection was implemented using boundary checks against the camera’s
orthographic limits. When the sphere reaches:
The left or right boundary → horizontal velocity is reversed.
The top or bottom boundary → vertical velocity is reversed.
Mathematically, reversing velocity simulates elastic collision behavior in simplified 2D
motion models.
To prevent the object from moving beyond boundaries, position clamping was used. This
ensures the sphere remains fully visible within the viewport.
Dynamic Color Modification
Each time a bounce occurs, the sphere’s material color is changed. A random color is
generated using the HSL color model.
Color models such as RGB and HSL are foundational to computer graphics rendering
systems (Shirley et al., 2020). Using HSL allows generation of visually distinct and
saturated colors.
The dynamic color change demonstrates understanding of material properties and runtime
property modification.
Shadow Behavior
As the sphere moves relative to the fixed directional light source, the illuminated and
shadowed regions change dynamically. The shadow on the ground plane shifts according
to the sphere’s position, confirming correct light-object interaction.
Shadow mapping visually reinforces spatial relationships and depth perception within the
scene (Akenine-Möller et al., 2018).
Learning Outcomes Demonstrated
This assignment successfully demonstrates:
Creation of a 3D geometric object
Application of translation transformations
Implementation of real-time animation
Collision detection and motion reversal
Dynamic color manipulation
Directional lighting and shadow mapping
Understanding of viewport boundaries in orthographic projection
Through this implementation, I gained practical experience applying theoretical computer
graphics principles to an interactive rendering environment.
CodePen Submission Links
Graphics View (Live Preview):
[Link]
Code View:
[Link]
JavaScript Code
<!--
Unit 3 Programming Assignment: Color, Blending, Transparency + Transformations
Requirements met:
- 3D object (Sphere)
- Small scale (covers small portion of viewport)
- Animated movement in x and y
- Bounces at viewport edges (like ball in box)
- Changes color on each bounce
- Light-yellow (FFFFAA) light source fixed at upper-left
- Shadows change as the object moves
- Code is heavily commented
-->
<div id="app"></div>
<script type="module">
// Import [Link] as an ES module (works in CodePen when placed in HTML as
type="module")
import * as THREE from "[Link]
// -------------------------------
// BASIC SCENE SETUP
// -------------------------------
const scene = new [Link]();
// Background similar to the assignment example image (olive/khaki-like)
[Link] = new [Link](0x9a9a6a);
// Renderer
const renderer = new [Link]({ antialias: true });
[Link]([Link], [Link]);
// Enable shadows so shadow areas appear on the sphere and ground
[Link] = true;
[Link] = [Link];
// Add renderer to the page
[Link]("app").appendChild([Link]);
// -------------------------------
// CAMERA (Orthographic makes “viewport limits” easy to define)
// -------------------------------
// frustumSize controls the visible "box" size
const frustumSize = 10;
const aspect = [Link] / [Link];
const camera = new [Link](
(-frustumSize * aspect) / 2, // left
(frustumSize * aspect) / 2, // right
frustumSize / 2, // top
-frustumSize / 2, // bottom
0.1,
100
);
[Link](0, 0, 12); // move camera back so we can see objects
[Link](0, 0, 0);
// -------------------------------
// LIGHTING (Fixed upper-left, light-yellow FFFFAA)
// -------------------------------
// A directional light simulates a distant light source.
// “Upper-left corner” relative to the scene can be represented as x negative, y positive.
const light = new [Link](0xffffaa, 1.2);
[Link](-8, 8, 10); // upper-left, slightly toward camera
[Link](light);
// Shadows from directional light
[Link] = true;
[Link] = 2048;
[Link] = 2048;
// Configure shadow camera bounds so shadow stays visible across the whole motion
area
[Link] = -15;
[Link] = 15;
[Link] = 15;
[Link] = -15;
[Link] = 0.1;
[Link] = 50;
// Add a small amount of ambient light so shadows aren’t fully black
[Link](new [Link](0xffffff, 0.25));
// -------------------------------
// GROUND PLANE (Receives shadow so you can clearly see shadow changes)
// -------------------------------
const groundGeometry = new [Link](50, 50);
const groundMaterial = new [Link]({
color: 0x7f7f55,
roughness: 1.0,
metalness: 0.0,
});
const ground = new [Link](groundGeometry, groundMaterial);
[Link].x = -[Link] / 2; // make it horizontal
[Link].y = -5; // lower it so sphere floats above it
[Link] = true;
[Link](ground);
// -------------------------------
// 3D OBJECT: SPHERE (small portion of viewport)
// -------------------------------
const radius = 0.6; // small size relative to frustumSize=10
const sphereGeometry = new [Link](radius, 48, 48);
// MeshStandardMaterial responds to light and shows shading/shadows well
const sphereMaterial = new [Link]({
color: 0x0033ff, // initial blue
roughness: 0.4,
metalness: 0.1,
});
const myMesh = new [Link](sphereGeometry, sphereMaterial);
[Link] = true; // sphere casts shadow
[Link] = false; // not necessary, but fine either way
[Link](myMesh);
// Start position
[Link](-2, 0, 0);
// -------------------------------
// MOTION / BOUNCE LOGIC
// -------------------------------
// Velocity controls movement per frame
let vx = 0.06;
let vy = 0.045;
// Viewport limits based on orthographic camera bounds
// Subtract radius so sphere edge touches boundary before bouncing
function getBounds() {
return {
minX: [Link] + radius,
maxX: [Link] - radius,
minY: [Link] + radius,
maxY: [Link] - radius,
};
}
// Random bright color generator (changes on each bounce)
function randomColor() {
const color = new [Link]();
[Link]([Link](), 0.85, 0.55); // bright, saturated
return color;
}
// -------------------------------
// ANIMATION LOOP
// -------------------------------
function animate() {
requestAnimationFrame(animate);
// Move the sphere by updating x and y each frame
[Link].x += vx;
[Link].y += vy;
// Check boundaries and bounce
const b = getBounds();
let bounced = false;
// Hit left or right edge?
if ([Link].x <= [Link] || [Link].x >= [Link]) {
vx *= -1; // reverse x direction
bounced = true;
// Clamp position so it doesn't "stick" outside boundary
[Link].x = [Link]([Link].x, [Link],
[Link]);
}
// Hit top or bottom edge?
if ([Link].y <= [Link] || [Link].y >= [Link]) {
vy *= -1; // reverse y direction
bounced = true;
// Clamp position
[Link].y = [Link]([Link].y, [Link],
[Link]);
}
// Change color on every bounce (edge encounter)
if (bounced) {
[Link] = randomColor();
}
// Render the scene
[Link](scene, camera);
}
animate();
// -------------------------------
// HANDLE RESIZE (keeps bounds correct)
// -------------------------------
[Link]("resize", () => {
const aspect = [Link] / [Link];
[Link] = (-frustumSize * aspect) / 2;
[Link] = (frustumSize * aspect) / 2;
[Link] = frustumSize / 2;
[Link] = -frustumSize / 2;
[Link]();
[Link]([Link], [Link]);
});
</script>
References
Akenine-Möller, T., Haines, E., & Hoffman, N. (2018). Real-time rendering (4th ed.).
CRC Press.
Shirley, P., Ashikhmin, M., & Marschner, S. (2020). Fundamentals of computer graphics
(4th ed.). CRC Press.