course note credit: some of slides are extracted from the course notes of prof. mathieu desburn...
TRANSCRIPT
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).
CSC 830 Computer GraphicsLecture 5
Rasterization
Rasterization• Okay, you have three points
(vertices) at screen space. How can you fill the triangle?
v0
v2
E2
E1
E0
v0
v1
E0
E1
E2
v1
v2
E1
1
12
2
Simple Solution
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;}
My simple approach
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; else 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
x1, y1, z1
x2, y2, z2
x3, y3, z3
(xn,yn,zn)
xn = x1 + (yn-y1)*(x2-x1)/(y2-y1)
zn = z1 + (yn-y1)*(z2-z1)/(y2-y1)
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).
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 AlgorithmSort objects in depth order
Draw all from Back-to-Front (far-to-near)
Is it so simple?
at z = 22, at z = 18, at z = 10,
1 2 3
X
Y
3D CyclesHow do we deal with cycles?
Deal with intersections
How do we sort objects that overlap in Z?
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
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
Non Trivial Example ?
Z-Buffer Advantages
Simple and easy to implement
Amenable to scan-line algorithms
Can easily resolve visibility cycles
Z-Buffer DisadvantagesAliasing 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
Scan Line AlgorithmsTake advantage of coherence in “insided-ness”
Inside/outside can only change at edge eventsCurrent edges can only change at vertex events
Scan Line AlgorithmsCreate 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.
Rule• Rule:
– 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
Active Edge Table (AET)
• A list of edges active for current scanline, sorted in increasing x
y = 9
y = 8
Penetrating Polygons
S
I
T
a
2
BG
b
c
3
d
e
1
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 valueFill between pairs of x in AETfor each edge in AET
if edge.ymax = yremove edge from AET
elseedge.x = edge.x + dx/dy
sort AET by x value
end scan_fill
For each scanline:1. Maintain active edge list (using vertex events)
2. Increment edge’s x-intercepts, sort by x-intercepts
3. Output spans between left and right edges
Scan Line Algorithms
delete insert replace
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 AlgorithmFind the vertex with the smallest y value to start
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
Crow’s AlgorithmScan upward maintaining the active edge list
(1)(3)
(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;
Crow’s AlgorithmDraw the spans
(2)
Increment the x value
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 AlgorithmDraw the spans
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);
Crow’s AlgorithmCalculate delta and starting values
df
d
f
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 AlgorithmFind the appropriate next left edge
(3)
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;
Crow’s AlgorithmInterpolating other values
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
ClippingObjects may lie partially inside and
partially outside the view volumeWe 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
Store inside/outside bitwise for each edge
Trivial acceptoutside(v1) | outside(v2) == 0
Trivial rejectoutside(v1) & outside(v2)
Compute intersection (eg. x = a)(a, y1 + (a-x1) * (y2-y1)/(x2-x1))
• 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.
Outcode Algorithm
if (outcode1 == '0000' and outcode2 == ‘0000’) then line segment is insideelse if ((outcode1 AND outcode2) == 0000) then line segment potentially crosses clip region else line is entirely outside of clip region endifendif
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 edgeReplace outside endpoint with intersection point
Repeat outcode test until trivial accept or reject
The maybe case?
CullingCheck whether all vertices lie outside the
clip plane
Speed up: first check bounding box extents
Flood FillHow to fill polygons whose edges are already drawn?
Choose a point inside, and fill outwards
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;
Flood FillFill a point and recurse to all of its neighbors
Area Subdivision (Warnock)
(mixed object/image space)
Clipping used to subdivide polygons that are across regions
Area Subdivision (Warnock)
1. Initialize the area to be the image plane
2. Four cases:1. No polygons in area: done2. One polygon in area: draw it3. Pixel sized area: draw closest polygon4. 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
cd
e
a
cb
e d
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 TreesCreating 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 BSPRender(eyePoint,b->positive); draw all polygons in b->coplanar; BSPRender(eyePoint,b->negative);
BSP TreesRendering the BSP Tree
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
Quad-trees• Quad-tree is the 2-D
generalization of binary tree– 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 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 Description• Set of Primitives• Specify for each primitive
• Transformation• Lighting attributes• Surface attributes
• Material (BRDF)• Texture• Texture transformation
Scene Graphs• Scene Elements
– Interior Nodes• Have children that inherit state• transform, lights, fog, color, …
– Leaf nodes• Terminal• geometry, text
– Attributes• Additional sharable state (textures)
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
• Simulation– Animation
• Intersection– Collision detection– Picking
• Image Generation– Culling– Detail elision– Attributes
Scene Graph Traversal
Scene Graph Considerations
• Functional Organization– Semantics
• Bounding Volumes– Culling– Intersection
• Levels of Detail– Detail elision– Intersection
• Attribute Management– Eliminate redundancies
Functional Organization• Articulated Transformations
– Animation– Difficult to optimize animated objects
Attribute Management• Minimize transformations
– Each transformation is expensive during rendering, intersection, etc. Need automatic algorithms to collapse/adjust transform hierarchy.
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?
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
PortalsTreat environment as a graphNodes = cells, Edges = portalsCell to cell visibility must go along edges