410 likes | 612 Views
Scan Conversion. Computer Graphics. OpenGL Pipeline. v 1 v2 v3. Model Transform. View Transform. Perspective Transform. Clipping. Perspective Division. Viewport Transform. Scan Conversion. Scan Conversion / Rasterization. Determines individual pixel values.
E N D
Scan Conversion Computer Graphics
OpenGL Pipeline v1 v2 v3 Model Transform View Transform Perspective Transform Clipping Perspective Division Viewport Transform Scan Conversion
Scan Conversion / Rasterization • Determines individual pixel values
Scan Converting Lines • Line Drawing • Draw a line on a raster screen between two points • What’s wrong with this statement of problem? • Doesn’t say anything about which points are allowed as end points • Doesn’t give a clear meaning of “draw” • Doesn’t say what constitutes a “line” in raster form • Doesn’t say how to measure success of proposed algorithm
Scan Converting Lines • Line Drawing • Problem Statement: • Given two points P and Q in XY plane, both with integer coordinates, determine which pixels on raster screen should be on in order to make picture of a unit width line segment starting at P and ending at Q
Scan Converting Lines • Special Cases: • Horizontal Line: • Draw pixel P and increment x coordinate value by 1 to get next pixel • Vertical Line: • Draw pixel P and increment y coordinate value by 1 to get next pixel • Diagonal Line: • Draw pixel P and increment both x and y coordinate value by 1 to get next pixel • General Case • What should we do in a general case? • Increment x coordinate by 1 and choose point closest to line. • How do we measure “closest”?
Vertical Distance • Why can we use vertical distance as a measure of which point is closer? • Because vertical distance is proportional to actual distance • We can show this with similar triangles • The true distances to line (in blue) are directly proportional to vertical distances to line (in black) • Therefore, point with smaller vertical distance to line is closest
Strategy 1 – Pseudocode void line (int x0, int y0, int x1, int y1) { int x, y; float dy = y1 – y0; float dx = x1 – x0; float m = dy / dx; //careful, check dx == 0 y = y0; for (x = x0; x < x1; ++x) { WritePixel (x, Round (y)); //Round is slow… y = y + m; } }
Strategy 2 –Brsenham’s Algorithm • Problem: • Given endpoints (Ax, Ay) and (Bx, By) of a line, determine the best sequence of intervening pixels to represent a line • First, make two simplifying assumptions: • (Ax < Bx) that is, moving from left to write • (0 < m < 1) that is, slope up and to the right at between (0 and 45 degrees) • We can remove both assumptions later… • Define • Width W = Bx – Ax • Height H = By - Ay
Strategy 2 – Brsenham’s Algorithm • Based on our assumptions: • W and H are positive • H < W • As x steps in the +1 increments, y can: • Stay the same • Increment by 1 • The key is to figure out which of these cases we want • Use the “midpoint” NE pixel E pixel Previous pixel
Strategy 2 – Brsenham’s Algorithm NE pixel Q Midpoint M E pixel Choices for next pixel Choices for current pixel Previous pixel
NE pixel E pixel Strategy 2 – Brsenham’s Algorithm • Line passes between E and NE • Point that is closer to intersection point must be chosen • Observe on which side of line midpoint lies: • E is closer to line if midpoint lies above line, i.e., line crosses bottom half • NE is closer to line if midpoint lies below line, i.e., line crosses top half • Error (vertical distance between chosen pixel and actual line) is always • Algorithm chooses NE as next pixel for line shown • Now we need to find a way to calculate on which side of the line the midpoint is
Strategy 2 – Brsenham’s Algorithm • Need a good equation to represent the line • The equation F(x, y) is doubled to avoid floats later… • Note that when F(x, y) == 0, then (x, y) is on the line • If (x, y) is not on the line, we get a positive or negative value for F • We can think of this as a measure of error (signed distance) to the line
Strategy 2 – Brsenham’s Algorithm • So: • F(x, y) = -2W (y – Ay) + 2H (x – Ax) • Algorithm: • Loop over x values: • If F(x, y) < 0, then: • (x, y) is above the line, so shade lower pixel (the E pixel) • Keep y the same • If F(x, y) > 0, then: • (x, y) is below the line, so shade upper pixel (the NE pixel) • y = y + 1
Strategy 2 – Brsenham’s Algorithm • Bonus: we can compute F(x, y) incrementally: • Initial midpoint M = (Ax+1, Ay+0.5) • Plugging into F(Mx, My) = -2W(y-Ay) + 2H(x-Ax) • We get an initial F = 2H – W • The next midpoint will be: • If y stays the same: F(Mx, My) += 2H • If y = y+1: F(Mx, My) += 2(W – H)
Brsenham’s Algorithm – Psueocode void Bresenham (IntPoint a, IntPoint b) { //assume a.x < b.x, and 0 < H/W < 1 int y = a.y; int W = b.x – a.x; int H = b.y – a.y; intF = 2*H – W; //current error term for (int x = a.x; x <= b.x; x++) { WritePixel (x, y); if (F < 0) { F += 2H; } else { y++; F += 2(H – W); } } }
Brsenham’s Algorithm – Assumptions • We had set some restrictions earlier: • 0 < m < 1 • Ax < Bx • These can be removed with some additional code: • For lines with Ax > Bx, swap the two points • For lines with m > 1, interchange x and y • For lines with m < 0, x++, y = y-1 rather than +1 • Horizontal and vertical lines (test for a.x == b.x)
(0, 17) (17, 0) Scan Converting Circles • Version 1: • Increment x • Find y value • WritePixel (x, y) • Terrible!
(0, 17) (0, 17) (17, 0) (17, 0) Scan Converting Circles • Version 1: • Increment x • Find y value • WritePixel (x, y) • Terrible! • Version 2: • Use polar coordinates • For angle from (0 to 360) • Find x, y • WritePixel (x, y) • Less bad…
(x0 + a, y0 + b) R (x0, y0) (x-x0)2 + (y-y0)2 = R2 Version 3 – Use Symmetry • Symmetry: • If (x0 + a, y0 + b) is on the circle, • So are (x0± a, y0 ±b) and (x0 ± b, y0 ± a) • Hence 8-way symmetry • Reduce the problem to finding the pixels for 1/8 of the circle
(x0, y0) Version 3 – Using Symmetry • Scan top right 1/8 of the circle with radius R • Circle starts at (x0, y0+R) • Let’s use another incremental algorithm with decision variable evaluated at midpoint
The Incremental Algorithm – A Sketch x = x0; y = y0 + R; WritePixel (x, y); for (x=x0+1; (x-x0) > (y-y0); x++) { if (decision_variable < 0) { //move east update decision variable; } else { //move south east update decision variable; y--; } WritePixel (x, y); } • Note, we can replace all occurrences of x0 and y0 with 0 (translate the coordinate system by (-x0, -y0)
The Incremental Algorithm • What we need: • Decision variable • Negative if we move E, positive if we move SE (or vice versa) • Follow the line strategy, use an equation • is zero on circle, negative inside, positive outside • If we are at pixel (x, y), we need to examine (x+1, y) and (x+1, y+1) • Compute f at the midpoint
The Decision Variable • Evaluate at the point (x+1, y – 0.5) • We are asking: “is f(x+1, y-0.5) positive or negative”? • Note that 0 means it is on the circle • If negative, midpoint is inside the circle, then we choose E • If positive, midpoint is outside of the circle, then we choose SE
Version 3 – Use Symmetry • The details of the implementation of the Brsenhamalgorithm for circles can be found in the book. • Just note that because of the curvature on the circle, the distance computation is a little trickier, especially if we want to use the same incremental computation as we did for lines. • There are additional optimizations that can make this faster • What kind of guarantee do we have from using the midpoint algorithm (for both line and circle)?
Midpoint Eighth Circle Algorithm MEC (R)/* 1/8th of a circle w/ radius R */{ int x =0, y = R; intdelta_E=2*x +3; intdelta_SE=2(x-y)+5; floatdecision=(x+1)*(x+1)+(y +0.5)*(y +0.5) –R*R; Pixel(x, y); while( y > x ){ if(decision >0){/* Move east */ decision +=delta_E; delta_E+=2;delta_SE+=2;/*Update delta*/ } else/* Move SE */ { y--; decision +=delta_SE; delta_E+=2;delta_SE+=4;/*Update delta*/ } x++; Pixel(x, y);}}
Other Scan Conversion Problems • Aligned Ellipses • Non-integer primitives • General conics • Patterned primitives
Patterned Lines • Patterned line from P to Q is not the same as patterned line from Q to P: • Patterns can be geometric or cosmetic • Cosmetic: texture applied after transformations • Geometric: pattern subject to transformations
Geometric vs Cosmetic + Cosmetic (Real-World Contact Paper) Geometric (Perspectivized/Filtered)
Filling a Polygon • Region to be filled is a polygon P, described as a set of vertices in raster (i.e. pixels), pi = (xi, yi), for i=1, 2, .., N. This sequence is sorted so that the vertices are in a pre-determined order. • To fill P, we work through the frame buffer, one scan line at a time, filling in the appropriate portions of each line. • The proper portions are determined by finding the intersections of the scan line with all edges of P.
Pseudocode For Filling Polygon foreach (scan line L) { Find intersections of L with all edges of P; Sort the intersections by increasing x-value; Fill pixel runs between all pairs of intersections; }
Filling Polygons – Additional Details • Additional details can be found in the text (calculating intersections, edge lists, etc.) • Which pixels belong to a polygon? • By convention, left and bottom colored, top and right are not.
OpenGL Pipeline v1 v2 v3 Model Transform View Transform Perspective Transform Clipping Perspective Division Viewport Transform Scan Conversion