Algorithms for drawing circle, and polygon
Download
Report
Transcript Algorithms for drawing circle, and polygon
Lecture 6
1. Scan conversion algorithm for circle
2. Draw polygons
3. Antialiasing
CP411 polygon
Draw a circle_ straight algorithm
#include <math.h>
const float DEG2RAD = 3.14159/180;
void drawCircle(float radius, float x, float y)
{
glBegin(GL_LINE_LOOP);
for (int i=0; i < 360; i++)
{
float degInRad = i*DEG2RAD;
glVertex2f(x+cos(degInRad)*radius, y+sin(degInRad)*radius);
}
glEnd
}
CP411 Computer Graphics
2
Midpoint point algorithm
● See class note
CP411 polygon
Polygon
● What is a polygon?
■ A geometric shape bounded by a closed polyline formed
by a sequence of vertices.
● Why choose polygon as a primitive ?
■ In interactive graphics, polygons rule the CG world
■ Two main reasons:
○ Can represent any surface with arbitrary accuracy
Splines, mathematical functions, etc.
○ Mathematical simplicity lends itself to simple, regular rendering
algorithms
CP411 polygon
Such algorithms embed well in hardware
Convex / Concave Polygons
● A two-dimensional shape is convex if and only if
every line segment connecting two points on the
boundary is entirely contained
● OpenGL can only draw convex polygon
■ How to recognize a convex polygon ?
CP411 polygon
OpenGL polygon command
● glBegin (GL_POLYGON)
specify vertices of the polygon
glend
● glPolygonMode( GLenum face, GLenum mode )
controls the
interpretation of polygons for rasterization
■ face Specifies the polygons that mode applies to. Must be GL_FRONT
for front-facing polygons, GL_BACK for back-facing polygons, or
GL_FRONT_AND_BACK for front- and back-facing polygons.
■ mode Specifies the way polygons will be rasterized. Accepted values
are GL_POINT, GL_LINE, and GL_FILL. The default is GL_FILL for
both front- and back-facing polygons.
CP411 polygon
Rasterizing Polygons
● Triangle is the minimal unit of a polygon
■ All polygons can be broken up into triangles
○ Convex, concave, complex
■ Triangles are guaranteed to be:
○ Planar
○ Convex
● We often draw polygons by breaking them into
triangles
CP411 polygon
Triangles
● Two basic methods for drawing triangles:
■ Edge walking
○ Use a line drawing algorithm to compute edges (edge setup)
○ Fill in pixels between edges
○ Finicky, lots of special cases
○ Touches only pixels involved in triangle
■ Edge equations
CP411 polygon
Edge Walking
● Basic idea:
■ Draw edges vertically
■ Fill in horizontal spans for each scanline
■ Interpolate colors down edges
■ At each scanline, interpolate
edge colors across span
CP411 polygon
Edge Walking: Notes
● Order vertices in x and y
■ 3 cases: break left, break right, no break
● Walk down left and right edges
■ Fill each span
■ Until breakpoint or bottom vertex is reached
● Advantage: can be made very fast
● Disadvantages:
■ Lots of finicky special cases
■ Need to pay attention to fractional offsets
CP411 polygon
Edge Walking: Notes
● Fractional offsets:
● Also: beware gaps between adjacent edges
CP411 polygon
Edge Equations
● An edge equation is simply the equation of the line
containing that edge
■ What is the equation of a 2D line?
■ Ax + By + C = 0
■ Given a point (x,y), what does plugging x & y into this
equation tell us?
■ Whether the point is:
○ On the line: Ax + By + C = 0
○ “Above” the line: Ax + By + C > 0
○ “Below” the line: Ax + By + C < 0
CP411 polygon
Edge Equations
● Edge equations thus define two half-spaces:
CP411 polygon
Edge Equations
● And a triangle can be defined as the intersection of
three positive half-spaces:
CP411 polygon
Edge Equations
● So…simply turn on those pixels for which all edge
equations evaluate to > 0:
-+ +
+CP411 polygon
Using Edge Equations
● Which pixels: compute min,max bounding box
● Edge equations: compute from vertices
● Orientation: ensure area is positive (why?)
CP411 polygon
Computing Edge Equations
● Want to calculate A, B, C for each edge from (xi, yi)
and (xj, yj)
● Treat it as a linear system:
Ax1 + By1 + C = 0
Ax2 + By2 + C = 0
● Notice: two equations, three unknowns
● Does this make sense? What can we solve?
● Goal: solve for A & B in terms of C
CP411 polygon
Computing Edge Equations
● Set up the linear system:
● Multiply both sides
by matrix inverse:
● Let C
y 0 A
1
C
y1 B
1
A
y1 y 0
C
B x0 y1 x1 y 0 x1 x0
= x0 y1 - x1 y0 for convenience
■ Then
CP411 polygon
x0
x1
A = y0 - y1 and B = x1 - x0
Computing Edge Equations: Numerical Issues
● We can avoid the problem in this case by using our
definitions of A and B:
A = y0 - y1
B = x 1 - x0
Thus:
C = -Ax0 - By0
or
CP411 polygon
C = x0 y1 - x1 y0
C = -Ax1 - By1
Edge Equations
● So…we can find edge equation from two verts.
● Given three corners C0, C1, C0 of a triangle, what
●
●
●
●
are our three edges?
How do we make sure the half-spaces defined by the
edge equations all share the same sign on the
interior of the triangle?
Be consistent (Ex: [C0 C1], [C1 C2], [C2 C0])
How do we make sure that sign is positive?
A: Test, and flip if needed (A= -A, B= -B, C= -C)
CP411 polygon
Edge Equations: Code
● Basic structure of code:
■ Setup: compute edge equations, bounding box
■ (Outer loop) For each scanline in bounding box...
■ (Inner loop) …check each pixel on scanline, evaluating
edge equations and drawing the pixel if all three are
positive
CP411 polygon
findBoundingBox(&xmin, &xmax, &ymin, &ymax);
setupEdges (&a0,&b0,&c0,&a1,&b1,&c1,&a2,&b2,&c2);
/* Optimize this: */
for (int y = yMin; y <= yMax; y++) {
for (int x = xMin; x <= xMax; x++) {
float e0 = a0*x + b0*y + c0;
float e1 = a1*x + b1*y + c1;
float e2 = a2*x + b2*y + c2;
if (e0 > 0 && e1 > 0 && e2 > 0)
setPixel(x,y);
}
}
CP411 polygon
General Polygon Rasterization
● Consider the following polygon:
D
B
C
A
E
F
● How do we know whether a given pixel on the
scanline is inside or outside the polygon?
CP411 polygon
General Polygon Rasterization
● Does it still work?
D
B
H
C
A
G
I
E
F
CP411 polygon
General Polygon Rasterization
● Basic idea: use a parity test
for each scanline
edgeCnt = 0;
for each pixel on scanline (l to r)
if (oldpixel->newpixel crosses
edge)
edgeCnt ++;
// draw the pixel if edgeCnt odd
if (edgeCnt % 2)
setPixel(pixel);
CP411 polygon
Faster Polygon Rasterization
● How can we optimize the code?
for each scanline
edgeCnt = 0;
for each pixel on scanline (l to r)
if (oldpixel->newpixel crosses edge)
edgeCnt ++;
// draw the pixel if edgeCnt odd
if (edgeCnt % 2)
setPixel(pixel);
● Big cost: testing pixels against each edge
● Solution: active edge table (AET)
CP411 polygon
Active Edge Table
● Idea:
■ Edges intersecting a given scanline are likely to intersect
the next scanline
■ Within a scanline, the order of edge intersections doesn’t
change much from scanline to scanline
CP411 polygon
Active Edge Table
● Algorithm:
■ Sort all edges by their minimum y coord
■ Starting at bottom, add edges with Ymin= 0 to AET
■ For each scanline:
○ Sort edges in AET by x intersection
○ Walk from left to right, setting pixels by parity rule
○ Increment scanline
○ Retire edges with Ymax < Y
○ Add edges with Ymin > Y
○ Recalculate edge intersections and resort (how?)
■ Stop when Y > Ymax for last edges
CP411 polygon
Edge Equations: Speed Hacks
● Some speed hacks for the inner loop:
int xflag = 0;
for (int x = xMin; x <= xMax; x++) {
if (e0|e1|e2 > 0) {
setPixel(x,y);
xflag++;
} else if (xflag != 0) break;
e0 += a0; e1 += a1; e2 += a2;
}
■ Incremental update of edge equation values
■ Early termination (why does this work?)
■ Faster test of equation values
CP411 polygon
Antialiasing
● What is aliasing?
The jaggies appeared in the drawings of lines are called aliasing.
It is due to the approximation of a continuous line with discrete pixels.
● Aliasing effects:
■
Distant objects may disappear entirely
■ Objects can blink on and off in animations
● Antialiasing techniques involve some
form of blurring to reduce contrast,
smoothen image
● Three antialiasing techniques:
■
Prefiltering
■ Postfiltering
■ Supersampling
CP411 polygon
Prefiltering
● Basic idea:
■ compute area of polygon coverage
■ use proportional intensity value
● Example: if polygon covers ¼ of the pixel
■ use ¼ polygon color
■ add it to ¾ of adjacent region color
● Cons: computing pixel coverage can be time
consuming
CP411 polygon
Prefiltering
● Conceive that a line is 1
pixel wide which covers
certain pixel squares.
● A simple drawing method sets the pixels in C, G, H and L to the
current color.
● Suppose that the overlapping proportion of a certain pixel is ,
the new pixel_color is then set to
current_color + (1- ) existing_color
CP411 polygon
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
Without antialiasing
CP411 polygon
With antialiasing
Supersampling
● Useful if we can compute color of any (x,y) value on
the screen
■ Increase frequency of sampling
■ Instead of (x,y) samples in increments of 1
■ Sample (x,y) in fractional (e.g. ½) increments
■ Find average of samples
● Example:
Double sampling = increments of ½ = 9 color
values averaged for each pixe
CP411 polygon
Postfiltering
● Supersampling uses average
■ Gives all samples equal importance
● Post-filtering: use weighting (different levels of
importance)
● Compute pixel value as weighted average
■ Samples close to pixel center given more weight
CP411 polygon