Lecture 3 - Simulate the World Now

Agenda for Today

We'll cover:

Announcements:

Review

Recall how we interpolate colors. Given some colors rgb1 (and likewise for 2, 3), we get the color of a pixel via:

v=αvc1+βvc2+γvc3

Where all α,β,γ are calculated in a way from Lecture 2 - The Big Picture (literally)#More on Barycentric Coordinate Intuition. Use this as a reference.

Later, we'll go to the GPU using OpenGL.

The Strike

This class is different since Zoe herself is a volunteer for the class (not a teacher). However, we're not going to campus. We'll be going on zoom, where they should be shorter to withold zoom fatigue.

Thursday is likely only going to be lab time.

Writing Software to Move to OpenGL

We first need to make our own rasterizer in order for us to use OpenGL and let that handle everything for us.

To start with, notice that we work in different spaces:

Really, a point like (3,2,1) in the world coordinates need to get mapped to some pixel coordinate like (20,112). A few notes on this:

We need ways to use data structures to get values from our pixels:

int W2PX(float xw) {
	return (C*xw + D); // scale by C and shift by D
}
int W2PY(float xy) {
	return (E*xy + F); // similar...
}

So how do we solve for our unknowns C,D,E,F?

Solving the Shifts and Scales...

We, as the programmers, can control the view volume (in OpenGL we actually get more tools to control this too!). We have a value for the:

Pop in

Things in video games may "pop in" since certain games may not render in items from outside the view volume.

You may want to literally name these values as the planes they represent:

float left = -1.0;
float right = 1.0;
float far = 0.0;
float near = 1.5;
//...

But we have some things to consider. We may have like a 2:3 aspect ratio, like if our window had moved. As a result, our objects may be desired to be "stetched" or "squished":

So usually, the user sets the window size (in pixels), thus the aspect ratio is also chosen by them. If we stretch in one direction, we want to still preserve the aspect ratio of the world coordinates:

// width, height are the window sizes
if (width > height)
{
	L = -width/height; // w > h -> L < -1
	R = width/height;  // R > 1
	B = -1;
	T = 1;
}
else 
{
	L = -1;
	R = 1;
	B = -H/W;
	T = H/W;
}

// where's the near and far? For now, we going to have near = 0 and far -> infty.
// we'll essentially just flatten the z-axis, so this won't matter as much.

Essentially, one of my volume dimensions, either x or y, are a unit size, while we set the other dimension to try to preserve the user's aspect ratio.

When the user changes the output, the programmer has to make the decision to:

Recentering + World to Pixel

Say we have a piano at (x,y,z)=(0,0,4000). It's clearly outside our view volume, so our goal is to not render anything outside of our view volume.

Really, if we're given some generic obj file, we sometimes want to, in case all the vertices are far out, normalizes the coordinates so that we can recenter the object back to our bounding box.

You'll be given most of the recentering code, but there's a tinyobj loader. One of these things computes the bounding box by doing this recentering. The worksheet below shows this as an example!

IMG_3077 1.jpeg

IMG_3078.jpeg

So for world to pixel, we'll need to use:

Cxw+D=xp

So when we set our values L, R, ... for our view planes, they are in world coordinates. The leftmost coordinate plane should become 0:

CL+D=0

And for the rightmost coordinate:

CR+D=width 1

And with two equations, we have two unknowns C,D, and we have knowns L,R,width 1, so we can solve this!!!

C=W1RL

Where C is defined as our scale factor. We can then plug in for C and solve for D:

D=CL

And do the exact same thing for y:

Eyw+F=ypEB+F=0,ET+F=H1E=H1TBF=EB

Once you have this, you can write your W2PX function:

vecN<int,2> W2PX(float x_w, float y_w)
{
	// solve our equation above for x
	// solve our equation above for y
	return vecN<int,2>(x_p, y_p);
}
int/int

Really make sure that you are casting our int/int to floats in the intermediary. If you just divide say 1/2 you get 0 since the int part truncates the decimal portion.

2D Image Domain

Refer mainly to [[References for week 1-2 2D coordinate transforms reference (Gortler).pdf]]. It has a lot of information regarding the 2D Image domain...

Who's in Front? (Z-buffer)

You're going to make a rasterizer following:

![[Rasterizer psuedocode.pdf]]

Coding Concepts

On the GPU, we'll need to literally send C-style arrays! This is because it's most efficient to send a pointer and a size to the GPU, rather than copying the data structures/classes inherent data.