Avoid any specific hardware or API because CG is a rapidly evolving field and the specifics of that knowledge are moving target.

Terminology: Modeling deals with the mathematical specification of shape and appearance properties in a way that can be stored on the computer. Rendering deals with the creation of shaded images from 3D computer models. Animation is a technique to create an illusion of motion through sequences of images.

User Interaction deals with the interface between input devices feedback to the user in imagery and other sensory feedback. Virtual Reality attempts to immerse the user into a 3D virtual world. Visualization to give users insight into

API

application program interface. a set of functions that perform basic operations such as drawing images and 3D surfaces into windows on the screen.

Graphics program needs to be able to use 2 related APIs: graphics API for visual output, UI API to get input from the user.

2 dominant paradigms for grpahics and UI:

  1. integrated approach. the graphics and UI toolkits are integrated and portable pkg that are fuly standardized and supported as part of the language.
  2. Direct3D, OpenGL. The drawing commands are part of a software library tied to a language such as C++, and the UI software is an independent entity that might vary from system to system.

Graphics Pipeline

A special software/hardware subsystem that efficiently draws 3D primitives in perspective. It maps 3D vertex locations to 2D screen pos and shade the triangles so that they both look realistic and appear in proper back-to-front order.

Drawing tris. in valid back-to-front order is always solved using z-buffer, which uses a special memory buffer to solve the problem in brute-froce manner. Geometrics manipulation uses 4D coordinates (3 traditioal geometric coords and a 4th homogeneous coords). LOD - level of detail. To minimize the number of tris. used to represent a model. Few tris. are needed in the far distance.

Almost all computers conform to the IEEE floating-point standard. It’s safe to make assumption about how numeric conditions I will handle.

3 special case:

  • Infinity. a valid number that is larger than all other valid numbers.
  • Minus Infinity. Smaller than all other valid numbers.
  • Not a Number (NaN). an invalid number that arises from an op with undefined consequences. e.g. 0 divided by 0

For any positive real number $a$, the following rules involving division by infinite values hold:

$$ \begin{align} +a / ( + \infty) = +0 \
-a / ( + \infty) = -0 \
+a / ( - \infty) = -0 \
-a / ( - \infty) = +0 \
\end{align} $$

IEEE floating-point has 2 representations for zeros: +0 and -0. The distinction barely matters, but it’s worth keeping in mind.

Other operations involving infinity values behave like:

$$ \begin{align} \infty + \infty = + \infty \
\infty - \infty = \text{NaN} \
\infty \times \infty = \infty \
\infty / \infty = \text{NaN} \
\infty / a = + \infty \
\infty / 0 = + \infty \
0/0 = \text{NaN} \end{align} $$

The boolean expression is expected:

$$-\infty < \text{valid numbers} < +\infty$$

Any arithmetic related to NaN gives results in NaN, and any boolean involving NaN is false.

It’s worth to note that IEEE floating-point handle “divide-by-zero”:

$$ \begin{align} +a / +0 = +\infty \
-a / +0 = -\infty \end{align} $$

This makes the programs smaller, robust and efficient.

$$a = \frac{1}{ \frac{1}{b} + \frac{1}{c}}$$

Normally, we might need to use two if statement check for b and c. However, when b = c = 0, it won’t crash the program. Instead, it will make the denominator infinity. One divided by infinity returns 0, so the a will be 0. if (a>0) then do something will also do the trick, because a>0 will only be true when a is a valid number that is greater than 0. NaN boolean expression always return false, and negative infinity is smaller than 0.

Efficiency

Pay more attention to memory access patterns than to operation counts. This is the opposite of the best heuristic functions two decades ago because the speed of memory has not kept pace with the speed of processors.

A reasonable approach:

  1. straightforward code. Compute intermediate results as needed on the fly rather than storing them.
  2. Compile in optimized mode.
  3. use profiling tools to find critical bottlenecks
  4. examine data structures to look for ways to improve locality. Make data unit sizes match the cache/page size on the target architecture
  5. examine the assembly code generated by the compiler for missed efficiencies if numeric computation is the bottlenecks. Rewrite source code to solve any problems.

Class Design

vector2 x and y component in a length-2 array so that indexing operator can be well supported. addition, subtraction, dot product, cross product, scalar multiplication, and scalar division.

vector3 a 3D vector class analogous to vector2

hvector a homogeneous vector with 4 components.

rgb an RGB color that stores 3 components.

transform 4x4 matrix for transformations. matrix multiply and member functions to apply to locations, directions, and surface normal vectors.

image. A 2D array of RGB pixels with an output operations.

Float vs. Double

keeping memory use down and maintaining coherent memory access are the keys to efficiency. using double-precision arithmetic avoids numerical problems. the trades off depends on the program.

Debug Strategies

The Scientific Method

create an image and observe what is wrong with it. Then we develop a hypothesis about what is causing the problem and test it.

Images as Coded Debugging Output

If I want to know the value of some variable for part of a computation that runs for every pixel, I can just modify the program temporarily to copy that value directly to the output image and skip the rest of the calculation that would normally be done. e.g. if I suspect the value is out of range, then I use a red pixel when the value is out of range.

Using a Debugger

  1. make sure the program is deterministic — run it in a single thread and make sure that all random numbers are computed from fixed seeds.
  2. find out which pixel or triangle is exhibiting the bug and add a statement before the suspected code.

Data Visualization for Debugging

make good plots and illustrations to understand what the data means. e.g. write code to visualize ray trees so you can see what paths contributed to a pixel, or in an image resampling routine you might make pots that show all the points where samples are being taken from the input.