Chapter 1: Pixels

Learning Objectives

By the end of this lecture, you will:

  • identify the important characteristics used to describe an image,
  • write basic JavaScript code,
  • investigate the frame rate of a fluid simulation.

Welcome to CS 461 :) I'm glad you're here and I'm excited to show you some techniques you can use to build interactive demos, visualizations, animations or games. We will cover several topics in this course, ranging from geometric modeling, ray-tracing, rasterization and animation. By the end of the course, you will be able to:

  1. develop your own ray tracer to render complex scenes,
  2. display and manipulate three-dimensional models using rasterization (with WebGL),
  3. animate three-dimensional objects and physical systems.

Those are the three main themes: ray tracing, rasterization (with WebGL) and animation. I will post notes (like the notes on this page) to our course website, which will also contain interactive demos within which you can modify some small code snippet to understand the concepts in that reading.

The Goal of Computer Graphics: Setting Pixel Colors

That's it, really. We're going to have a grid of pixels to represent a picture (we'll call this a frame) and our job is to assign the color of each pixel. Well, that's not quite the end of the story. We need to do this very quickly and, in some situations, we might be limited by how much memory we can use to do this.

Let's take a step back first. What's a pixel anyway? A pixel is a "PIcture ELement" and it's the main building block of the pictures you see in your everyday life, like the pictures you take on your phone.

Consider the 8-bit image of the earth at the top-left of this page (originally from here) in which we can see the individual pixels. How many total colors are used here? I count four: black for the background, white for the stars, green for land and blue for the ocean.

There are a few important things we need to consider when assigning pixel colors in an image:

  1. What is the size of the image? In other words, how many pixels are there along the width and height of the picture? The more pixels you have, the more memory your image will take up, and the more work your computer will do to process your image.
  2. How do we represent the color assigned to each pixel? In general, we will use a red-green-blue (RGB) triplet to represent the color. In some cases each channel (red, green or blue) will have an integer value from 0-255 but in others we will assign floating-point values between 0-1.
  3. What is the coordinate system of the image, i.e. what are the directions of the x- (width) and y- (height) axes? We will always use a coordinate system in which x- goes from left to right. However, some graphics systems have the y-axis pointing downwards.

Check out the following demo. On the left, you should see a rotatable and zoomable 3d model of a cow (a common model called "Spot"). Each point on the surface of Spot is translated to a pixel and, again, our job is to assign a color to that pixel. Later in the course, we will study WebGL, which will consist of writing shaders to programatically assign these pixel colors. For now, the pixel color is set to grey (0.5, 0.5, 0.5). Actually, you might notice there is a light that makes some points look brighter, but we'll talk about this in a few weeks when we talk about shading. The base modelColor is grey. Exercise 1: try adjusting the RGB values of the modelColor.

Okay, let's make this more interesting and add a flannel pattern. Exercise 2: try typing the following mathematical expression given the coordinates on the surface of Spot (x, y and z). Feel free to change the 100.0 and also the 3d model using the dropdown below!

if (sin(100.0 * x) < 0.0 && sin(100.0 * y) < 0.0 && sin(100.0 * z) < 0.0)
    modelColor = vec3(.4, 0, 0);
else
    modelColor = vec3(0.1, 0.1, 0.1);

Also, what happens if you change one of the 0.0 in the conditional to 0?

Frame Rate

Let's investigate a bit further. Here is a really nice demo of a fluid simulation. Click on the link to open the demo and then click/drag to simulate the fluid! What do you notice if you increase the "resolution" setting to 1024? 4096? 8192? Have a look at the FPS display at the top-left.

https://philipclaude.github.io/webgl-fluids-demo/

Please note: I did not write this really nice demo! I just modified some of the resolution settings. The original code can be found here.

So let's restate our goal. We want to set the color of every pixel in a frame at some appropriate framerate. The framerate is measured in frames per second and often abbreviated FPS. The human eye can typically see between 30-60 FPS. Anything below that and the animation/simulation/interaction will feel "off".

JavaScript

JavaScript may look familiar if you've programmed in Java, C or C++, in terms of the use of semi-colons, curly braces and the syntax of if-statements and for loops. Everything in JavaScript is an object (numbers, strings, classes, etc.). There are some amazing online resources for learning JavaScript - for an in-depth guide, please have a look at Eloquent JavaScript or w3schools.

There's often more than one way of doing something in JavaScript, and our use of the language will be quite basic. AirBnB's style guide is a good resource for learning the dos and don'ts of JavaScript (which we will mostly follow). You'll be able to pick up JavaScript along the way, but be sure to review things like:

To avoid bugs, I recommend the following:

As you read through these lecture notes, I will embed mini exercises that will prompt you to either modify some JavaScript code, or even one of the shaders (written in GLSL), as in the demo above. However, especially when you work on your labs, you should be familiar with a few other ways to develop in JavaScript code. First (and probably the most convenient), you can use the JavaScript console in your browser (Chrome: View -> Developer -> JavaScript console, Firefox: Tools -> Web Developer -> Web Console, Safari: Develop -> Show JavaScript Console). When you open the "console", you will face a prompt which looks like >; You can use the console to create objects, perform calculations - just like you would with a Python interpreter.

Examples

Here are some examples of basic JavaScript code syntax. Please open the JavaScript console and directly type the examples below (you can copy-paste some of the longer examples). The comments below the expressions demonstrate what the output should be when printing the variable.

Variables and Printing
let x = 2; // declare a variable
x = 3; // change the value

const y = 8; // declare a const variable
// y = 9; // <-- ERROR!

// printing
console.log('x + y = ', x + y);  // method 1
console.log(`x + y = ${x + y}`); // method 2 with template literals
Arrays, Loops and Conditionals
let a = new Array(10); // an array with 10 elements
for (let i = 0; i < a.length; ++i) {
  if (i % 2) a[i] = i + 1;
  else a[i] = 0;
}
// a = [0, 2, 0, 4, 0, 6, 0, 8, 0, 10]

a.push(1); // add an eleventh element
// a = [0, 2, 0, 4, 0, 6, 0, 8, 0, 10, 1]

// ternary conditional operator
const b = (a.length % 5) ? 34 : 7;
// b = 7

// another way to create an array
let x = [];
x.push(5);
x.push(8);
// x = [5, 8]
Functions

There are different ways to declare functions. The first method below (regular function) is hoisted and is generally not recommended. AirBnB recommends either using arrow functions or named function expressions - the latter have an advantage over anonymous function expressions when examining the strack trace of a program (e.g. when debugging). Arrow functions are preferred when assigning callbacks and the function needs to be anonymous (as in the last example).

// regular function (hoisted)
function add1(x, y) {
  return x + y;
}

// anonymous function expression (not hoisted)
let add2 = function(x, y) {
  return x + y;
};

// named function expression (not hoisted)
let add3 = function addsTwoNumbers(x, y) {
  return x + y;
}

// arrow functions (not hoisted)
let add4 = (x, y) => {
  return x + y;
};

console.log(add1(1, 2)); // 3
console.log(add2(2, 3)); // 5
console.log(add3(3, 4)); // 7
console.log(add4(4, 5)); // 9

// setting the callback when a key is pressed for the web page
window.addEventListener('keydown', (event) => {
  console.log(event.key, ' was pressed!');
});
// then click on the main page to bring it into focus and press some keys!
Classes and Objects
class Pixel {
  constructor(r, g, b) {
    this.r = r;
    this.g = g;
    this.b = b;
  }

  scale(a) {
    this.r *= a;
    this.g *= a;
    this.b *= a;
  }
}

let p = new Pixel(0.5, 0.5, 0.5); // create a pixel object
// p.r = 0.5, p.y = 0.5, p.z = 0.5

p.scale(255);
// p.r = 127.5, p.y = 127.5, p.z = 127.5

The scale method was defined directly in the class definition. Alternatively, we can define methods outside of the class using prototypes (although it isn't recommended by AirBnB):

Pixel.prototype.set = function(r, g, b) {
  this.r = r;
  this.g = g;
  this.b = b;
}
p.set(1, 0, 0);
// p.r = 1, p.g = 0, p.b = 0

Also note that objects can be created directly using JSON:

const canvasInfo = {
  'id': 'myHtmlCanvas',
  'width': 600,
  'height': 400
};
console.log(canvasInfo.width); // 600

© Philip Caplan, 2025