CS488 2D Graphics Luc RENAMBOT 1
Topics Last time, hardware and frame buffer Now, how lines and polygons are drawn in the frame buffer. Then, how 2D and 3D models drawing into the frame buffer Then, more realistic 2D and 3D models 2
Mathematics vs. Engineering We like to think about a scene as mathematical primitives in a world-space This scene is then rendered into the frame buffer. Logical separation of the world from the view of that world Points are infinitely small Line segments are infinitely thin Elements converted into discrete pixels an obvious easy efficient way 3
Scan Conversion of a line Process called rasterization Take an analytic (continuous) function and convert (digitize) it OpenGL example in world-space: glbegin(gl_line_strip); glvertex2f(1.5, 3.0); glvertex2f(4.0, 4.0); glend(); 4
Polygons OpenGL polygons are very restricted to improve speed Edges can not intersect (simple polygons) Polygon must be convex, not concave 5
Outline or Filled triangle Outline glbegin(gl_line_loop); glvertex2f(1.5, 3.0); glvertex2f(4.0, 4.0); glvertex2f(4.0, 1.0); glend(); Filled glbegin(gl_polygon); glvertex2f(1.5, 3.0); glvertex2f(4.0, 4.0); glvertex2f(4.0, 1.0); glend(); 6
Drawing process From world-space into viewport coordinates 2D world to 2D frame buffer 3D world to 2D frame buffer Viewport coordinates used to draw lines and polygons Two approaches Human-friendly Computer-friendly 7
Simple algorithm Given a line segment from leftmost (Xo,Yo) to rightmost (X1,Y1) Y=mX+B m = deltay / deltax = (Y1 - Yo) / ( X1 - Xo) Start = round(xo) Stop = round(x1) for (Xi = Start; Xi <= Stop; Xi++) illuminate Xi, round(m * Xi + B); 8
Problems Each iteration has: Comparison Fractional multiplication Two additions Call to round() Addition is OK, fractional multiplication is bad, and a function call is very bad as this is done A LOT So we need more complex algorithms which use simpler operations to increase the speed 9
Importance of the Slope m=1 then each row and each column have a pixel filled in 0 <= m< 1 then each column has a pixel and each row has >= 1, so we increment X each iteration and compute Y m > 1 then each row has a pixel and each column has >= 1, so we increment Y each iteration and compute X 10
Simple Incremental Algorithm Y=mX+B m = deltay / deltax = (Y1 - Yo) / ( X1 - Xo) if deltax is 1 then deltay is m so if X(i+1) = X(i) + 1 then Y(i+1) = Y(i) + m 11
Simple Incremental Algorithm m < 1, Starting at the leftmost edge of the line X = round(xo) Y = Yo while (X <= X1) repeatedly illuminate X, round(y) add 1 to X (moving one pixel column to the right) add m to Y 12
Features + incremental - rounding is a time consuming operation(y) - real variables have limited precision, can cause a cumulative error in long line segments (e.g. 1/3) - Y must be a floating point variables 13
Midpoint Line Algorithm Assuming Xo,X1,Yo,Y1 are integers Assuming 0 <= m <= 1, we start at the leftmost edge of the line, and move right one pixel-column at a time illuminating the pixel either in the current row (the pixel to the EAST) or the next higher row (the pixel to the NORTHEAST) 14
Midpoint Line Algorithm Assuming Xo,X1,Yo,Y1 are integers Assuming 0 <= m <= 1, we start at the leftmost edge of the line, and move right one pixel-column at a time illuminating the pixel either in the current row (the pixel to the EAST) or the next higher row (the pixel to the NORTHEAST) 14
Equation rewriting Form F(X,Y) = ax + by + c = 0 Y = (deltay / deltax) * X + B 0 = (deltay / deltax) * X - Y + B 0 = deltay * X - deltax * Y + deltax * B F(X,Y) = deltay * X - deltax * Y + deltax * B 15
Properties So for any point (Xi,Yi), we can plug Xi,Yi into the above equation and F(Xi,Yi) = 0 then (Xi,Yi) is on the line F(Xi,Yi) > 0 then (Xi,Yi) is below the line F(Xi,Yi) < 0 then (Xi,Yi) is above the line 16
Algorithm Given that we have illuminated the pixel at (Xp,Yp), we will next either illuminate the pixel to the EAST (Xp+ 1,Yp) or the pixel to the NORTHEAST (Xp+ 1,Yp+ 1) 17
Selection Midpoint between the EAST and NORTHEAST pixel and see which side of the midpoint the line falls on line above the midpoint illuminate the NORTHEAST pixel line below the midpoint illuminate the EAST pixel line exactly on the midpoint CHOOSE TO illuminate the EAST pixel d = F(Xp+1,Yp+0.5) 18
If EAST Midpoint is incremented by 1 in X and 0 in Y We want to compute the new d without recomputing d from the new Midpoint dcurrent = F(Xp + 1,Yp + 0.5) Apply F(X,Y) dnew = dcurrent + deltay 19
If NORTHEAST Midpoint is incremented by 1 in X and 1 in Y We want to compute the new d without recomputing d from the new Midpoint dcurrent= F(Xp + 1,Yp + 0.5) Apply F(X,Y) dnew = dcurrent + deltay - deltax 20
Initial conditions Initial point (Xo,Yo) is known So initial M is at (Xo + 1, Yo + 0.5) So initial d = deltay - deltax / 2 Since (Xo,Yo) is on the line -> F(Xo,Yo) = 0 Division by 2 is removed by multiplying F(X,Y) Since d is only concerned with =0,< 0, or > 0 multiplication does not affect it 21
Algorithm deltax = X1 - Xo deltay = Y1 - Yo d = deltay * 2 - deltax deltae = deltay * 2 deltane = (deltay - deltax) * 2 X = Xo Y = Yo illuminate X, Y while (X < X1) repeatedly if ( d <= 0) add deltae to d add 1 to X else add deltane to d add 1 to X add 1 to Y illuminate X, Y The full algorithm is given (in Pascal) in the white book as figure 3.8 on p. 78 22
Features + incremental + only addition done in each iteration + all integer variables What if the line segment starts on the right and proceeds to the left? with plain lines you could reverse the endpoints and draw the line from left to right as described above. If the line has a pattern this simplification will not work What about lines with slope < 0 or slope > 1? some modifications needed 23
Filling a Polygon Want to avoid drawing pixels twice Pixels within the boundary of a polygon belong to the polygon Pixels on the left and bottom edges belong to a polygon, but not the pixels on the top and right edges Want a polygon filling routine that handles convex, concave, intersecting polygons and polygons with interior holes 24
Overall idea Moving from bottom to top up the polygon Starting at a left edge, fill pixels in spans until you come to a right edge 25
Algorithm Moving from bottom to top up the polygon 1. Find intersections of the current scan line with all edges of polygon 2. Sort intersections by increasing x coordinate 3. Moving through list of increasing x intersections Parity bit = even (0) Each intersection inverts the parity bit Draw pixels when parity is odd (1) 26
Scan-line algorithm As usual there is the straightforward easy way and the convoluted efficient way An easy way: Given that each line segment can be described using X = Y/m + B Each scan line covering the polygon has a unique integer Y value from Ymin to Ymax Plugging each of these Y values into the equation gives the corresponding fractional X value These values could then be sorted and stored 27
Next time More Polygon Filling Clipping 28