CSC 830 Computer Graphics Lecture 5

Presentation on theme: "CSC 830 Computer Graphics Lecture 5"— Presentation transcript:

CSC 830 Computer Graphics Lecture 5
Rasterization Course Note Credit: Some of slides are extracted from the course notes of prof. Mathieu Desburn (USC) and prof. Han-Wei Shen (Ohio State University).

Rasterization Okay, you have three points (vertices) at screen space. How can you fill the triangle? v2 E1 Simple Solution v2 v1 2 E1 E1 1 2 v1 1 E2 E0 E0 E2 v0 v0

My simple approach int draw_tri(render,t) GzRender *render;
GzTriangle t; { sort_vert(t); /* Vertices are properly sorted, so edge1 can be composed by ver[0],ver[1] and edge2 by ver[1],[2], and so on */ init_edge(render,E0,t[0],t[1]); init_edge(render,E1,t[1],t[2]); init_edge(render,E2,t[0],t[2]); step_edges(render); return GZ_SUCCESS; }

void init_edge(GzRender *render,int i,GzVertex ver1,GzVertex ver2)
{ Interpolater *ip; float dy; ip = &render->interp[i]; ip->fromx = ver1.p[x]; ip->fromy = ver1.p[y]; dy = ver2.p[y]-ver1.p[y]; if(dy== 0) ip->dxdy = zmax; else ip->dxdy = (ver2.p[x]-ver1.p[x])/dy; ip->tox = ver2.p[x]; ip->toy = ver2.p[y]; ip->fromz = ver1.p[z]; if(ver2.p[y]-ver1.p[y]== 0) ip->dz = zmax; ip->dz =(ver2.p[z]-ver1.p[z])/dy; vec_copy(ip->from_norm,ver1.n); ip->dnorm[x]=(ver2.n[x] - ver1.n[x])/dy; ip->dnorm[y]=(ver2.n[y] - ver1.n[y])/dy; ip->dnorm[z]=(ver2.n[z] - ver1.n[z])/dy; }

Interpolater x3, y3, z3 x2, y2, z2 (xn,yn,zn)
xn = x1 + (yn-y1)*(x2-x1)/(y2-y1) zn = z1 + (yn-y1)*(z2-z1)/(y2-y1) x1, y1, z1

Step Edges v2 v2 v2 v1 v1 v0 v1 v0 E1 v1 v2 v0 v2 v2 E1 v1 E2 E0 E2 E1

Better & still simple approach
Find left edge & right edge from v0 You can not tell when y==v0.y But you can tell by comparing x values when y == v0.1+1 You need to treat horizontal edges carefully (divide by zero).

How can you handle this?

Or this?

Back-face Culling If a surface’s normal is pointing to the same direction as our eye direction, then this is a back face The test is quite simple: if N * V > 0 then we reject the surface

Painters Algorithm Sort objects in depth order
Draw all from Back-to-Front (far-to-near) Is it so simple?

3D Cycles How do we deal with cycles? Deal with intersections
How do we sort objects that overlap in Z?

Z-buffer Z-buffer is a 2D array that stores a depth value for each pixel. Invented by Catmull in '79, it allows us to paint objects to the screen without sorting, without performing intersection calculations where objects interpenetrate. InitScreen:     for i := 0 to N do         for j := 1 to N do        Screen[i][j] := BACKGROUND_COLOR;  Zbuffer[i][j] := ; DrawZpixel (x, y, z, color)       if (z <= Zbuffer[x][y]) then              Screen[x][y] := color; Zbuffer[x][y] := z;

Z-buffer: Scanline I.  for each polygon do        for each pixel (x,y) in the polygon’s projection do              z := -(D+A*x+B*y)/C;              DrawZpixel(x, y, z, polygon’s color); II.  for each scan-line y do        for each “in range” polygon projection do              for each pair (x1, x2) of X-intersections do                   for x := x1 to x2 do                          z := -(D+A*x+B*y)/C;                          DrawZpixel(x, y, z, polygon’s color); If we know zx,y at (x,y) than:    zx+1,y = zx,y - A/C

Z-buffer - Example

Non Trivial Example ? Rectangle: P1(10,5,10), P2(10,25,10), P3(25,25,10), P4(25,5,10) Triangle: P5(15,15,15), P6(25,25,5), P7(30,10,5) Frame Buffer: Background 0, Rectangle 1, Triangle 2 Z-buffer: 32x32x4 bit planes

Z-Buffer Advantages Simple and easy to implement
Amenable to scan-line algorithms Can easily resolve visibility cycles

Aliasing occurs! Since not all depth questions can be resolved Anti-aliasing solutions non-trivial Shadows are not easy Higher order illumination is hard in general

Rasterizing Polygons Given a set of vertices and edges,
find the pixels that fill the polygon.

Scan Line Algorithms Take advantage of coherence in “insided-ness”
Inside/outside can only change at edge events Current edges can only change at vertex events

Scan Line Algorithms Create a list of vertex events (bucket sorted by y)

Scan Line Algorithms Create a list of the edges intersecting the first scanline Sort this list by the edge’s x value on the first scanline Call this the active edge list

Scanline Rasterization Special Handling
Intersection is an edge end point, say: (p0, p1, p2) ?? (p0,p1,p1,p2), so we can still fill pairwise In fact, if we compute the intersection of the scanline with edge e1 and e2 separately, we will get the intersection point p1 twice. Keep both of the p1.

Scanline Rasterization Special Handling

Rule Rule: Don’t count p1 for e2
If the intersection is the ymin of the edge’s endpoint, count it. Otherwise, don’t. Don’t count p1 for e2

Data Structure Edge table: all edges sorted by their ymin coordinates.
keep a separate bucket for each scanline within each bucket, edges are sorted by increasing x of the ymin endpoint

Edge Table

Active Edge Table (AET)
A list of edges active for current scanline, sorted in increasing x y = 9 y = 8

Penetrating Polygons False edges and new polygons!
Compare z value & intersection when AET is calculated

Polygon Scan-conversion Algorithm
Construct the Edge Table (ET); Active Edge Table (AET) = null; for y = Ymin to Ymax Merge-sort ET[y] into AET by x value Fill between pairs of x in AET for each edge in AET if edge.ymax = y remove edge from AET else edge.x = edge.x + dx/dy sort AET by x value end scan_fill

Scan Line Algorithms For each scanline:
Maintain active edge list (using vertex events) Increment edge’s x-intercepts, sort by x-intercepts Output spans between left and right edges delete insert replace

Convex Polygons Convex polygons only have 1 span
Insertion and deletion events happen only once

Crow’s Algorithm crow(vertex vList[], int n) int imin = 0;
Find the vertex with the smallest y value to start crow(vertex vList[], int n) int imin = 0; for(int i = 0; i < n; i++) if(vList[i].y < vList[imin].y) imin = i; scanY(vList,n,imin);

Crow’s Algorithm Scan upward maintaining the active edge list
scanY(vertex vList[], int n, int i) int li, ri; // left & right upper endpoint indices int ly, ry; // left & right upper endpoint y values vertex l, dl; // current left edge and delta vertex r, dr; // current right edge and delta int rem; // number of remaining vertices int y; // current scanline li = ri = i; ly = ry = y = ceil(vList[i].y); for( rem = n; rem > 0) // find appropriate left edge // find appropriate right edge // while l & r span y (the current scanline) // draw the span (1) (3) (2)

Crow’s Algorithm Draw the spans for( ; y < ly && y < ry; y++)
(2) for( ; y < ly && y < ry; y++) // scan and interpolate edges scanX(&l, &r, y); increment(&l,&dl); increment(&r,&dr); increment(vertex *edge, vertex *delta) edge->x += delta->x; Increment the x value

Crow’s Algorithm Draw the spans scanX(vertex *l, vertex *r, int y)
int x, lx, rx; vertex s, ds; lx = ceil(l->x); rx = ceil(r->x); if(lx < rx) differenceX(l, r, &s, &ds, lx); for(x = lx, x < rx; x++) setPixel(x,y); increment(&s,&ds);

Crow’s Algorithm Calculate delta and starting values d f d f
differenceX(vertex *v1, vertex *v2, vertex *e, vertex *de, int x) difference(v1, v2, e, de, (v2->x – v1->x), x – v1->x); difference(vertex *v1, vertex *v2, vertex *e, vertex *de, float d, float f) de->x = (v2->x – v1->x) / d; e->x = v1->x + f * de->x; differenceY(vertex *v1, vertex *v2, vertex *e, vertex *de, int y) difference(v1, v2, e, de, (v2->y – v1->y), y – v1->y); d f d f

Crow’s Algorithm Find the appropriate next left edge
(3) while( ly < = y && rem > 0) rem--; i = li – 1; if(i < 0) i = n-1; // go clockwise ly = ceil( v[i].y ); if( ly > y ) // replace left edge differenceY( &vList[li], &vList[i], &l, &dl, y); li = i;

Crow’s Algorithm Interpolating other values
difference(vertex *v1, vertex *v2, veretx *e, vertex *de, float d, float f) de->x = (v2->x – v1->x) / d; e->x = v1->x + f * de->x; de->r = (v2->r – v1->r) / d; e->r = v1->r + f * de->r; de->g = (v2->g – v1->g) / d; e->g = v1->g + f * de->g; de->b = (v2->b – v1->b) / d; e->b = v1->b + f * de->b; increment( vertex *v, vertex *dv) v->x += dv->x; v->r += dv->r; v->g += dv->g; v->b += dv->b;

Scan Line Algorithm Low memory cost Uses scan-line coherence
but not vertical coherence Has several side advantages: filling the polygons reflections texture mapping Renderman (Toy Story) = scan line

Visibility Clipping Culling

Clipping Objects may lie partially inside and partially outside the view volume We want to “clip” away the parts outside Simple approach - checking if (x,y) is inside of screen or not What is wrong with it?

Cohen-Sutherland Clipping
Clip line against convex region Clip against each edge Line crosses edge replace outside vertex with intersection Both endpoints outside trivial reject Both endpoints inside trivial accept

Cohen-Sutherland Clipping

Cohen-Sutherland Clipping
Store inside/outside bitwise for each edge Trivial accept outside(v1) | outside(v2) == 0 Trivial reject outside(v1) & outside(v2) Compute intersection (eg. x = a) (a, y1 + (a-x1) * (y2-y1)/(x2-x1))

Outcode Algorithm Classifies each vertex of a primitive, by generating an outcode. An outcode identifies the appropriate half space location of each vertex relative to all of the clipping planes. Outcodes are usually stored as bit vectors.

if (outcode1 == '0000' and outcode2 == ‘0000’) then
line segment is inside else if ((outcode1 AND outcode2) == 0000) then line segment potentially crosses clip region line is entirely outside of clip region endif

The maybe case? If neither trivial accept nor reject: Pick an outside endpoint (with nonzero outcode) Pick an edge that is crossed (nonzero bit of outcode) Find line's intersection with that edge Replace outside endpoint with intersection point Repeat outcode test until trivial accept or reject

The Maybe case

The Maybe Case

Culling Removing completely invisible objects/polygons

Culling Check whether all vertices lie outside the clip plane
Speed up: first check bounding box extents

Backface Culling For closed objects, back facing polygons are not visible Backfacing iff: n v

Flood Fill How to fill polygons whose edges are already drawn?
Choose a point inside, and fill outwards

Flood Fill Fill a point and recurse to all of its neighbors
floodFill(int x, int y, color c) if(stop(x,y,c)) return; setPixel(x,y,c); floodFill(x-1,y,c); floodFill(x+1,y,c); floodFill(x,y-1,c); floodFill(x,y+1,c); int stop(int x, int y, color c) return colorBuffer[x][y] == c;

Area Subdivision (Warnock) (mixed object/image space)
Clipping used to subdivide polygons that are across regions

Area Subdivision (Warnock)
Initialize the area to be the image plane Four cases: No polygons in area: done One polygon in area: draw it Pixel sized area: draw closest polygon Front polygon covers area: draw it Otherwise, subdivide and recurse

BSP (Binary Space Partition) Trees
Partition space into 2 half-spaces via a hyper-plane a b b c a e e d c d

BSP Trees Creating the BSP Tree BSPNode* BSPCreate(polygonList pList)
if(pList is empty) return NULL; pick a polygon p from pList; split all polygons in pList by p and insert pieces into pList; polygonList coplanar = all polygons in pList coplanar to p; polygonList positive = all polygons in pList in p’s positive halfspace; polygonList negative = all polygons in pList in p’s negative halfspace; BSPNode *b = new BSPNode; b->coplanar = coplanar; b->positive = BSPCreate(positive); b->negative = BSPCreate(negative); return b;

BSP Trees Rendering the BSP Tree
BSPRender(vertex eyePoint, BSPNode *b) if(b == NULL) return; if(eyePoint is in positive half-space defined by b->coplanar) BSPRender(eyePoint,b->negative); draw all polygons in b->coplanar; BSPRender(eyePoint,b->positive); else

BSP Trees Advantages view-independent tree anti-aliasing (see later)
transparency Disadvantages many small polygons over-rendering hard to balance tree

Spatial Data Structures
Data structures for efficiently storing geometric information. They are useful for Collision detection (will the spaceships collide?) Location queries (which is the nearest post office?) Chemical simulations (which protein will this drug molecule interact with?) Rendering (is this aircraft carrier on-screen?), and more Good data structures can give speed up rendering by 10x, 100x, or more

Bounding Volume Simple notion: wrap things that are hard to check for ray intersection in things that are easy to check. Example: wrap a complicated polygonal mesh in a box. Ray can’t hit the real object unless it hits the box Adds some overhead, but generally pays for itself . Can build bounding volume hierarchies

Bounding Volumes Choose Bounding Volume(s) Spheres Boxes
Parallelepipeds Oriented boxes Ellipsoids Convex hulls

node (cell) is a square recursively split into four equal sub-squares stop when leaves get “simple enough”

Octrees Octree is the 3-D generalization of quad-tree
node (cell) is a cube, recursively split into eight equal sub- cubes stop splitting when the number of objects intersecting the cell gets “small enough” or the tree depth exceeds a limit internal nodes store pointers to children, leaves store list of surfaces more expensive to traverse than a grid adapts to non-homogeneous, clumpy scenes better

K-D tree The K-D approach is to make the problem space a rectangular parallelepiped whose sides are, in general, of unequal length. The length of the sides is the maximum spatial extent of the particles in each spatial dimension.

K-D tree

K-D Tree in 3-D Similarly, the problem space in three dimensions is a parallelepiped whose sides are the greatest particle separation in each of the three spatial dimensions.

Motivation for Scene Graph
Three-fold Performance Generality Ease of use How to model a scene ? Java3D, Open Inventor, Open Performer, VRML, etc.

Scene Graph Example

Scene Graph Example

Scene Graph Example

Scene Graph Example

Scene Description Set of Primitives Specify for each primitive
• Transformation • Lighting attributes • Surface attributes Material (BRDF) Texture Texture transformation

Scene Graphs Scene Elements Interior Nodes Leaf nodes Attributes
Have children that inherit state transform, lights, fog, color, … Leaf nodes Terminal geometry, text Attributes Additional sharable state (textures)

Scene Element Class Hierarchy

Scene Graph Graph Representation What do edges mean?
Inherit state along edges group all red object instances together group logical entities together parts of a car Capture intent with the structure

Scene Graph

Scene Graph (VRML 2.0)

Example Scene Graph

Scene Graph Traversal Simulation Intersection Image Generation
Animation Intersection Collision detection Picking Image Generation Culling Detail elision Attributes

Scene Graph Considerations
Functional Organization Semantics Bounding Volumes Culling Intersection Levels of Detail Detail elision Attribute Management Eliminate redundancies

Functional Organization
Semantics: Logical parts Named parts

Functional Organization
Articulated Transformations Animation Difficult to optimize animated objects

Bounding Volume Hierarchies

View Frustum Culling

Level Of Detail (LOD) Each LOD nodes have distance ranges

Attribute Management Minimize transformations
Each transformation is expensive during rendering, intersection, etc. Need automatic algorithms to collapse/adjust transform hierarchy.

Attribute Management Minimize attribute changes
Each state change is expensive during rendering

Question: How do you manage your light sources?
OpenGL supports only 8 lights. What if there are 200 lights? The modeler must ‘scope’ the lights in the scene graph?

Sample Scene Graph

Think! How to handle optimization of scene graphs with multiple competing goals Function Bounding volumes Levels of Detail Attributes

Scene Graphs Traversal
Perform operations on graph with traversal Like STL iterator Visit all nodes Collect inherited state while traversing edges Also works on a sub-graph

Typical Traversal Operations
Typical operations Render Search (pick, find by name) View-frustum cull Tessellate Preprocess (optimize)

Scene Graphs Organization
Tree structure best No cycles for simple traversal Implied depth-first traversal (not essential) Includes lists, single node, etc as degenerate trees If allow multiple references (instancing) Directed acyclic graph (DAG) Difficult to represent cell/portal structures

Portals Separate environment into cells
Preprocess to find potentially visible polygons from any cell

Portals Treat environment as a graph Nodes = cells, Edges = portals
Cell to cell visibility must go along edges