22
Implementation
Ed Angel
Professor of Computer Science, Electrical and Computer Engineering,
and Media Arts
University of New Mexico
Many changes – Jeff Parker
2
Outline
Homework:Past
RotationsLost World
FutureFractals and Chaos
Implementation
23
Homework
Several students had trouble with Eigen Vectors
€
0 0 −1
0 −1 0
−1 0 0
⎡
⎣
⎢ ⎢ ⎢
⎤
⎦
⎥ ⎥ ⎥
a
b
c
⎛
⎝
⎜ ⎜ ⎜
⎞
⎠
⎟ ⎟ ⎟=
a
b
c
⎛
⎝
⎜ ⎜ ⎜
⎞
⎠
⎟ ⎟ ⎟
−c
−b
−a
⎛
⎝
⎜ ⎜ ⎜
⎞
⎠
⎟ ⎟ ⎟=
a
b
c
⎛
⎝
⎜ ⎜ ⎜
⎞
⎠
⎟ ⎟ ⎟
−c = a
−b = b
−a = c
(a,b,c) = (1,0,−1)
4
Gallery
• I downloaded some images…
Dan – Tigers and Bats
5
Gallery
• I downloaded some images…
Charles – Birdcage
6
Gallery
• I downloaded some images…
Alex – Ritual Dance
7
Outline
We will be looking ahead to the next assignment – FractalsStart with Koch SnowflakeHeighway Dragon CurveLindenmayer Systems (aka L-Systems)
Application to drawing TreesMandelbrot Set
Three waysLook at Angel's example, which you may extend
If we have time, we will dip our toes into Chaos
8
Fractals - Snowflake curve
Koch Snowflake was discovered by Helge von Koch in 1904. Start with a triangle inscribed in the unit circleTo build the level n snowflake, we replace each edge in the
level n-1 snowflake with the following patternThe perimeter of each version is 4/3 as long
Infinite perimeter, but snowflake lies within unit circle, so has finite area
9
Dimension of Koch Curve
If we measure the length of this room with a yardstick and get 4 units, and measure again with a foot ruler, we would expect to see 12 units.
If we measure the area of this room with a unit yard square and get 30 units, and then measure with a unit foot square, we would expect to get 270 units.
The length is one dimensional, and the area is two dimensional
10
Length of Curve
How long is the perimeter?Assume I have a yardstick, and the original triangle edge is
36 inchesLength is 3 yards, or 9 feet
Now assume I have a foot ruler. Cannot span a yard: each edge is now 4 feet long
Length is 12 feet
If I use a smaller ruler, the length is even longer
11
How long is the coast of Britain?
How Long Is the Coast of Britain? Statistical Self-Similarity and Fractional Dimension, by Benoit Mandelbrot
12
Dimension of Koch Curve
If we measure the length of this room with a yardstick and get 4 units, and measure again with a foot ruler, we would expect to see 12 units.
If we measure the area of this room with a unit yard square and get 30 units, and then measure with a unit foot square, we would expect to get 270 units.
The length is one dimensional, and area is two dimensional
The length of the Koch snowflake is neither 1 dimensional (length grows)
2 dimensional (doesn't grow fast enough)
It is given a fractional dimension:
€
ln 4
ln 3=1.26186
13
More images
14
Two papers
Real Time Design and Animation of Fractal Plants and Trees - Peter E. Oppenheimer
Flocks, Herds, and Schools: A Distributed Behavioral Model - Craig W. Reynolds
Hugo Elias - http://freespace.virgin.net/hugo.elias/models/m_main.htm
15
Dragon Curve
The Dragon Curve is due to Heighway
One way to generate the curve is to start with a folded piece of paper
We can describe a curve as a set of turtle directions
The second stage is simply
Take one step, turn Right, and take one step
The next stage is
Take one step, turn Right, take one step
Turn Right
Perform the original steps backwards, or
Take one step, turn Left, take one step
Since the step between turns is implicit, we can write this as RRL
The next stage is
…
16
Dragon Curve
The Dragon Curve is due to Heighway
One way to generate the curve is to start with a folded piece of paper
We can describe a curve as a set of turtle directions
The second stage is simply
Take one step, turn Right, and take one step
The next stage is
Take one step, turn Right, take one step
Turn Right
Perform the original steps backwards, or
Take one step, turn Left, take one step
Since the step between turns is implicit, we can write this as RRL
The next stage is
RRL R RLL
17
How can we program this?
We could use a large array representing the turns
RRL R RLL
To generate the next level, append an R and walk back to the head, changing L’s to R’s and R’s to L’s and appending the result to end of array
But there is another way.
Start with a line
At every stage, we replace the line with a right angle
We have to remember which side of the line to decorate (use variable “direction”)
One feature of this scheme is that the “head” and “tail” are fixed
R R L R R L L
18
Dragon Curve
void dragon(int size, int level, int direction, int alpha)
{
/* Add on left or right? */
int degree = direction * 45;
turtleSet(alpha);
if (1 == level) {
turtleDrawLine(size);
return;
}
size = size/scale; /* scale == sqrt(2.0) */
dragon(size, level - 1, 1, alpha + degree);
dragon(size, level - 1, -1, alpha - degree);
}
19
Dragon Curve
When we divide an int (size) by a real (sqrt(2.0)) there is roundoff error, and the dragon slowly shrinks
Myversion of this program precomputes sizes per level and passes them through, as below
int sizes[] = {0, 256, 181, 128, 90, 64, 49, 32, 23, 16, 11, 8, 6, 4, 3, 2, 2, 1, 0};
...
dragon(sizes[level], level, 1, 0);
...
void dragon(int size, int level, int direction, int alpha)
{
...
/* size = size/scale; */
dragon(size, level - 1, 1, alpha + degree);
dragon(size, level - 1, -1, alpha - degree);
}
20
Gosper Flowsnake
21
Lindenmayer Systems
Rewriting rulesStart:
S
Rewrite RuleS -> S R S L L S R S
Lindenmayer's first systemStart
A
RewriteA -> ABB -> A
Start with SSS
22
Lindenmayer Systems
variables : 0, 1constants: [, ]Start: 0Rewrite Rules : (1 → 11), (0 → 1[0]0)Start: 01st recursion: 1[0]02nd recursion: 11[1[0]0]1[0]03rd recursion: 1111[11[1[0]0]1[0]0]11[1[0]0]1[0]0
23
Lindenmayer Systemsvariables : 0, 1constants: [, ]Start: 0Rewrite Rules : (1 → 11), (0 → 1[0]0)Start: 01st recursion: 1[0]02nd recursion: 11[1[0]0]1[0]03rd recursion: 1111[11[1[0]0]1[0]0]11[1[0]0]1[0]00: draw a line segment ending in a leaf1: draw a line segment[: push position and angle, turn left 45 degrees]: pop position and angle, turn right 45 degrees
Tree
This is harder to do from scratch
Jon Squire's fractalgl
static void generate(float x, float y, float widtht, float height,
float angle, int level)
{
...
if (level>0)
{
turtle_theta = point(x, y, x1, y01);
turn(left_angle);
generate(turtle_x, turtle_y, left_width_factor*widtht,
left_height_factor*height, left_angle, level);
turtle_theta = point(x, y, x1, y01);
turn(-right_angle);
generate(x1, y01, left_width_factor*widtht,
left_height_factor*height, right_angle, level);
}
} /* end generate */
Jon Squire's fractalgl
static void generate(float x, float y, float widtht, float height,
float angle, int level)
{
...
if(level<3)
{
glColor3f(0.0, 1.0, 0.0);
drawbranch(widtht, (int)x, (int)y, (int)x1, (int)y01);
}
else
{
glColor3f(0.0, 0.0, 0.0);
drawbranch(widtht, (int)x, (int)y, (int)x1, (int)y01);
}
...
} /* end generate */
Jon Squire's fractalgl
27
Mandlebrot Set
Interesting Fractal
http://www.youtube.com/watch?v=gEw8xpb1aRA
Has a wide range of interesting habitats
Self Similar
28
Mandelbrot Set
The Mandelbrot Set M is based on work by Fatou and Julia
Description of set M is quite indirect
Define a function fc from the
complex plane to itself
fc : C ---> C
fc(z) = z2 + c
29
Mandelbrot Set
fc : C ---> C
fc(z) = z2 + c
We look at iterations of fc upon the point z0 = 0
fc3(z0) = fc
3(0) = fc(fc(fc(0)))
We say c is in the Mandelbrot Set M if
lim fcn(z0) is finite as n goes to infinity
30
Let’s compute some short examples
Reminder: fc(z) = z2 + c
If c = 0, the sequence fcn(0) is f0(0) = z2 + 0 = 0
0, 0, 0, 0, 0, 0… So point 0 is in the set
If c = 1, the sequence fcn(0) is f1(0) = z2 + 1
0, 1, 2, 5, 26, … So point 1 is not in the set
(We start with fc0(0) = 0 in all examples)
If c = 1/2, the sequence fcn(0) is
0, 1/2, 3/4, 1 1/16, 1 161/256, … So 1/2 is not in the set
If c = -2, the sequence fcn(0) is
0, -2, 2, 2, 2… So point -2 is in the set
If c = -1, the sequence fcn(0) is periodic
0, -1, 0, -1, 0, -1… So point -1 is in the set
If c = i, the sequence fcn(0) is fi(0) = z2 + i
0, i, -1 + i, -i, -1 + i, -i… So point i is in the set
31
Computing Mandelbrot Set
We say c is in the Mandelbrot Set M if
lim fcn(0) does not go to infinity as n goes to infinity
Practically, we say that point c is not in M if for some k,
| fck(0) | > 2 where fc(z) = z2 + c
Our algorithm is:
For each c in the complex plane, build function fc
Iterate, computing fck(0) until magnitude is greater than 2, or k > MAX
Color the screen – here are three alternatives
Directly through glDrawPixels() call – Angel 5th Edition
Build a texture and pass it to the GPU – Angel 6th Edition, version 1 7E
Let the GPU color each point – Angel 7th Edition
Assignment32
Assignment
Add comments to explain what Angel is doing.
Rework the color scheme. Usually items in the set are colored black, and points outside the set are given different colors depending on the number of iterations it takes to escape a circle of radius 2.
Revise the computation in the main loop to reduce the amount of work
Add a mouse handler to control zooming in and out. You will find it simplest to take a mouse click, translate to model coordinates, and then recalibrate.
A single click should zoom in.
A shift click should zoom out.
Center the drawing on the point clicked
The current version uses floats: to explore the set in detail, you may want to use doubles to hold the values.
33
Mouse Callback
When the user clicks on the screen, want to map from screen coordinates back to world coordinates
Take that as the new center, and change the width we display
Halve size if shift is not down (zoom in)
Double size if shift is down (zoom out)
It may be simplest to keep the center of the screen and a "radius"
When we click hereZoom in centered on this point
35
7th Edition V2
<script id="fragment-shader" type="x-shader/x-fragment">
precision mediump float;
uniform float cx;
uniform float cy;
uniform float scale;
float height;
float width;
void main()
{
//float height = 0.5; /* size of window in complex plane */
//float width = 0.5;
36
7th Edition V2
<script id="fragment-shader" type="x-shader/x-fragment">
precision mediump float;
uniform float cx;
uniform float cy;
uniform float scale;
float height;
float width;
void main()
{
//float height = 0.5; /* size of window in complex plane */
//float width = 0.5;
37
7th Edition V2
void main()
{
const int max = 100; /* number of interations per point */
const float PI = 3.14159;
float n = 500.0;
float m = 500.0;
float v;
float x = gl_FragCoord.x /(n*scale) + cx - 1.0 / (2.0*scale);
float y = gl_FragCoord.y/(m*scale) + cy - 1.0 / (2.0*scale);
float ax=0.0, ay=0.0;
float bx, by;
38
7th Edition V2
for ( int k = 0; k < max; k++ ) {
// compute c = c^2 + p
bx = ax*ax-ay*ay;
by = 2.0*ax*ay;
ax = bx+x;
ay = by+y;
v = sqrt(ax*ax+ay*ay);
if ( v > 4.0 ) /* assume not in set if mag > 4 */
break;
}
// assign gray level to point based on its magnitude */
39
7th Edition V2
for ( int k = 0; k < max; k++ ) {
// compute c = c^2 + p
bx = ax*ax-ay*ay;
by = 2.0*ax*ay;
ax = bx+x;
ay = by+y;
v = sqrt(ax*ax+ay*ay);
if ( v > 4.0 ) /* assume not in set if mag > 4 */
break;
}
// assign gray level to point based on its magnitude */
40
7th Edition V2
v = sqrt(ax*ax+ay*ay);
if ( v > 4.0 ) /* assume not in set if mag > 4 */
break;
}
// assign gray level to point based on magnitude */
//if ( v > 1.0 ) v = 1.0; /* clamp if > 1 */
v = min(v, 1.0);
gl_FragColor.r = v;
gl_FragColor.g = 0.5* sin( 2.0*PI*v) + 1.0;
gl_FragColor.b = 1.0-v;
gl_FragColor.a = 1.0;
}
</script>
41
Color Scheme
We say c is in the Mandelbrot Set M if
lim fcn(0) does not go to infinity as n goes to infinity
Practically, we say that point c is not in M if for some k,
| fck(0) | > 2 where fc(z) = z2 + c
The algorithm for the image above is:
For each c in the complex plane, build function fc
Iterate, computing fck(0) until magnitude is greater than 2, or k > MAX
If k is MAX, color point c black (c is in the set)
If k is small, color point c blue (really cold: escaped quickly)
If k is large, color point c red (really warm: almost made it into the set)
We use random green values at different levels to give contours
42
Mapping back
How do you take a position and map back to the real coordinates?
What does a click here mean?Map this back to the x and y coordinate
Image is N pixels wide
43
Other Ideas
Many other fractals we have not mentioned
Hilbert curves
Julia Sets
Dynamical Systems and Chaos
Lorenz
Rosseler
http://math.bu.edu/DYSYS/
http://www.stsci.edu/~lbradley/seminar/index.html
http://hypertextbook.com/chaos/
23
Objectives
Introduce basic implementation strategies
Clipping
Drawing lines
Anti-aliasing
Drawing Circles
Scan conversion
Two contributions from Robert Sproullcoauthor of first text on Computer Graphics
23
Resources
A number of papers posted on iSite
Bresenham through Program Transformations - Sproull
Line Drawing, Leap Years, and Euclid – Harris
Fast Line Scan Conversion – Rokne
A New Concept and Method for Line Clipping – Liang and Barsky
An Efficient Antialiasing Technique – Wu
Hugo Elias - http://freespace.virgin.net/hugo.elias/graphics/x_main.htm
24
Overview
At end of the geometric pipeline, vertices have been assembled into primitives
Must clip primitives that are outside view frustumAlgorithms based on representing primitives by
lists of verticesMust find which pixels can be affected by each
primitiveFragment generationRasterization or scan conversion
25
Required Tasks
Clipping
Rasterization or scan conversion
Transformations
Some tasks deferred until fragment processing
Hidden surface removal
Antialiasing
26
Rasterization Meta Algorithms
Consider two approaches to rendering a scene with opaque objects
For every pixel, determine which object that projects on the pixel is closest to the viewer and compute the shade of this pixelRay tracing paradigm
For every object, determine which pixels it covers and shade these pixelsPipeline approachMust keep track of depths
27
Clipping
2D against clipping window3D against clipping volumeEasy for line segments polygonsHard for curves and text
Convert to lines and polygons first
28
Clipping 2D Line Segments
Brute force approach: compute intersections with all sides of clipping window
Inefficient: one division per intersection
29
Cohen-Sutherland Algorithm
Idea: eliminate as many cases as possible without computing intersections
Start with four lines that determine the sides of the clipping window
x = xmaxx = xmin
y = ymax
y = ymin
30
The Cases
Case 1: both endpoints of line segment inside all four lines
Draw (accept) line segment as is
Case 2: both endpoints outside all lines and on same side of a line
Discard (reject) the line segment
x = xmaxx = xmin
y = ymax
y = ymin
31
The Cases
Case 3: One endpoint inside, one outsideMust do at least one intersection
Case 4: Both outsideMay have part inside
Must do at least one intersection
x = xmaxx = xmin
y = ymax
32
Defining Outcodes
For each endpoint, define an outcode
Outcodes divide space into 9 regionsComputation of outcode requires at most 4 subtractions
b0b1b2b3
b0 = 1 if y > ymax, 0 otherwiseb1 = 1 if y < ymin, 0 otherwiseb2 = 1 if x > xmax, 0 otherwiseb3 = 1 if x < xmin, 0 otherwise
Cohen-Sutherland Algorithm
http://www.cs.princeton.edu/~min/cs426/jar/clip.html
33
Using Outcodes
Consider the 5 cases below
AB: outcode(A) = outcode(B) = 0Accept line segment
34
Using Outcodes
CD: outcode (C) = 0, outcode(D) ≠ 0Compute intersection
Location of 1 in outcode(D) determines which edge to intersect with
Note if there were a segment from A to a point in a region with 2 ones in outcode, we might have to do two interesections (see addition)
35
Using Outcodes
EF: outcode(E) logically ANDed with outcode(F) (bitwise) ≠ 0
Both outcodes have a 1 bit in the same place
Thus and is non-zero
Line segment is outside of corresponding side of clipping window
Reject
36
Using Outcodes
GH and IJ: same outcodes, neither zero but logical AND yields zero – no easy reject
Shorten line segment by intersecting with one of sides of window
Compute outcode of intersection (new endpoint of shortened line segment)
Reexecute algorithm
Cohen-Sutherland Algorithm
http://www.cs.princeton.edu/~min/cs426/jar/clip.html
37
Cohen Sutherland Efficiency
In many applications, the clipping window is small relative to the size of the entire data base
Most line segments are outside one or more side of the window and can be eliminated based on their outcodes
Inefficiency when code has to be reexecuted for line segments that must be shortened in more than one step
38
Cohen Sutherland in 3D
Use 6-bit outcodes
When needed, clip line segment against planes
39
Liang-Barsky Clipping
Consider the parametric form of a line segment
We can distinguish between the cases by looking at the ordering of the values of α where the line determined by the line segment crosses the lines that determine the window
p(α) = (1-α)p1+ αp2 1 ≥ α ≥ 0
p1
p2
40
Liang-Barsky Clipping
In (a): α4 > α3 > α2 > α1
Intersect right, top, left, bottom: shorten
In (b): α4 > α2 > α3 > α1
Intersect right, left, top, bottom: reject
41
Advantages
Can accept/reject as easily as with Cohen-Sutherland
Using values of α, we do not have to use algorithm recursively as with C-S
Extends to 3D
42
Clipping and Normalization
General clipping in 3D requires intersection of line segments against arbitrary plane
Example: oblique view
43
Plane-Line Intersections
Note that any distance measure can be usede.g. Projection onto x axis
3
Rasterization
Rasterization (scan conversion)Determine which pixels are inside primitive
specified by a set of vertices
Produces a set of fragments
Fragments have a location and other attributes such color and texture coordinates that are determined by interpolating values at vertices
Pixel colors determined later using color, texture, normal, and other vertex properties
4
Scan Conversion of Line Segments
Start with line segment in window coordinates with integer values for endpoints
Assume implementation has a write_pixel function
y = mx + h
Draw a Line
We start with the problem of drawing a line between two pixels
Without loss, assume we have line with positive slope and p1 is on left of p2
Goals
We want to draw the right pixels
(What are they?)
We want to do it quickly
We want to do it correctly
We want to handle all cases
Bresenhamyi = y1; r = 2(y2-y1) - (x2-x1)
for (x = x1; x <= x2; x++)
draw_pixel(x, yi)
if (r >= 0)
yi = yi + 1;
r = r + 2∆y - 2∆x
else
r = r + 2∆y
xx yyii rr
00 0 -2
11 0 2
22 1 -6
33 1 -2
Draw a Line
Where did those numbers come from?
We will derive Bresenham’s algorithm
Derivation due to Sproull: Using Program Transformations to Derive Line-Drawing Algorithms
Take 1
float m = (y2-y1)/(x2-x1);
for (x = x1; x <= x2; x++) {
y = m*(x - x1) + y1
draw_pixel(x, y)
}
Speedup
float m = (y2-y1)/(x2-x1);
y = y1
for (x = x1; x <= x2; x++)
draw_pixel(x, y)
y = y + m
Replace multiplication with addition
Problems
Works well if delta y <= delta x
Otherwise, we need to reverse the roles
So the “right” points mean
At least one in each row and column from start to finish
We add assumption that delta y <= delta x for now
Problemsfloat m = (y2-y1)/(x2-x1);
for (x = x1; x <= x2; x++)
draw_pixel(x, y)
y = y + m
m is not an integer (But m is rational)
Therefore values of y are not integral
But we can only draw integral pixels
Draw Integeral Pointsm = (y2-y1)/(x2-x1);
y = y1
for (x = x1; x <= x2; x++)
draw_pixel(x, round(y))
y = y + m
Rather than use round(), we say
draw_pixel(x, trunc(y + 1/2))
Error Term
We want to minimize the error
The best way to measure the error is the distance to the line, as measured by perpendicular
Since we have fixed slope, this is proportional to the vertical distance
9
Candidate Pixels
1 ≥ m ≥ 0
last pixel
candidates
Note that line could havepassed through any
part of this pixel
Examples
Draw lines from (0, 0) to (8, n) for n = 0 through 8
Beforem = (y2-y1)/(x2-x1);
y = y1
for (x = x1; x <= x2; x++)
draw_pixel(x, trunc(y + 1/2))
y = y + m
Restate - move additionm = (y2-y1)/(x2-x1);
y = y1 + 1/2
for (x = x1; x <= x2; x++)
draw_pixel(x, trunc(y))
y = y + m
We move addition of ½ outside loop to simplify
draw_pixel(x, trunc(y + 1/2))
Restate - move additionm = (y2-y1)/(x2-x1);
y = y1 + 1/2
for (x = x1; x <= x2; x++)
draw_pixel(x, trunc(y))
y = y + m
x is an int, while m and y are real numbers
But m is a rational number, so y is as well
Split ym = (y2-y1)/(x2-x1);
y = y1 + 1/2
Split y into two parts: integer and fraction
y = yi+ yf
0 <= yf < 1
yi = y1
yf = 1/2Goal: decide when yi increases
Restate with split ym = (y2-y1)/(x2-x1); // 2/6 in our example
yi = y1; yf = 1/2
for (x = x1; x <= x2; x++)
draw_pixel(x, yi)
if (yf + m) >= 1
yi = yi + 1; // Bump y
yf = (yf + m) - 1;
else yf = (yf + m)
yf = yf + m
x is an int: m and yf are rational numbers
xx yyii yyff yyii yyff
00 0 1/2
11 0 5/6
22 1 7/6 1 1/6
33 1 3/6
Introduce variable rRecall m = ∆y / ∆x = (y2-y1)/(x2-x1)
So (m * ∆x) is an integer – ∆y
To convert 1/2 to an integer, multiply by 2
Introduce new form of error term: let
r = 2∆y + 2(yf - 1)∆x
At start yf = 1/2, so at start
r = 2∆y – 2(1/2 – 1)∆x = 2∆y + ∆x
Change in rr = 2∆y + 2(yf - 1)∆x // r is a measure of error
Increasing yf by slope m is increasing r by 2∆y
r = 2∆y + 2(yf + m - 1)∆x =
= 2∆y + 2(yf - 1)∆x + 2(∆y/∆x) ∆x
= 2∆y + 2(yf - 1)∆x + 2∆y
Decreasing yf by 1 is decreasing r by 2∆x
r = 2∆y + 2(yf -1 - 1)∆x = 2∆y + 2(yf - 1)∆x - 2∆x
Restate with ryi = y1; r = 2(y2-y1) - (x2-x1)
for (x = x1; x <= x2; x++)
draw_pixel(x, yi)
if (r >= 0)
yi = yi + 1;
r = r + 2∆y - 2∆x
else
r = r + 2∆y
xx yyii rr
00 0 -2
11 0 2
22 1 -6
33 1 -2
Reconsider
All the steps seem small: let’s review
We made assumptions to simplify things
Boils down to the following case:
As x moves from left to right, which y?
We have two choices: old y or y+1
?
?
Jaggies
Our lines have visible steps
We are sampling the line at too coarse a level
We could make the dots smaller
Effect remains
We could use a "low pass filter" to smooth it out
Low pass filter smears details together
20
Antialiasing by Area Averaging
Color multiple pixels for each x depending on coverage by ideal line
original antialiased
magnified
Wu Antialiasing
Xialin Wu - An Efficient Antialiasing Technique
Assume plotting a function f() with 0 ≤ m ≤ 1
Consider this example: we have sampled function f at three points
Wu Antialiasing
Given the graph in the upper part
We would digitize this with as below
First point is rounded down to lattice
Second point is rounded up to lattice
This misrepresents the shape
Had we moved the graph up or down, would have digitized differently
Wu Antialiasing
Given the graph in the upper part
We would digitize this with as below
First point is rounded down to lattice
Second point is rounded up to lattice
This misrepresents the shape
Had we moved the graph up or down, would have digitized differently
Wu AntialiasingIdea: Bracket point with 2 pixels
North-South when m < 1
East-West when m > 1
Darkness is proportional to closeness to line
€
I[i, f (i)⎣ ⎦] = I0 ( f (i)⎡ ⎤− f (i))
I[i, f (i)⎡ ⎤] = I0 ( f (i)⎣ ⎦− f (i))
Wu AntialiasingWork through an example
We are using the ceiling and floor functions
€
I[i, f (i)⎣ ⎦] = I0 ( f (i)⎡ ⎤− f (i))
I[i, f (i)⎡ ⎤] = I0 ( f (i)⎣ ⎦− f (i))
ExampleWork through an example (0, 0) to (5, 2)
Compute values of f(x) at x = {0, 1, 2, 3, 4, 5}
€
I[i, f (i)⎣ ⎦] = I0 ( f (i)⎡ ⎤− f (i))
I[i, f (i)⎡ ⎤] = I0 ( f (i)⎣ ⎦− f (i))
ExampleWork through an example (0, 0) to (5, 2)
Compute Intensity at x = {0, 1, 2, 3, 4, 5}
€
I[i, f (i)⎣ ⎦] = I0 ( f (i)⎡ ⎤− f (i))
I[i, f (i)⎡ ⎤] = I0 ( f (i)⎣ ⎦− f (i))
€
(0, 0)
(1, 0.4)
(2, 0.8)
(3, 1.2)
(4,1.6)
(5, 2)
ExampleWork through an example (0, 0) to (5, 2)
Compute Intensity at x = {0, 1, 2, 3, 4, 5}
€
I[i, f (i)⎣ ⎦] = I0 ( f (i)⎡ ⎤− f (i))
I[i, f (i)⎡ ⎤] = I0 ( f (i)⎣ ⎦− f (i))
€
(0, 0)
(1, 0.4)
(2, 0.8)
(3, 1.2)
(4,1.6)
(5, 2)
1, [2/5, 3/5], [4/5, 1/5], [1/5, 4/5], [3/5, 2/5], 1
Algorithmdraw_pixel(x0,y0); draw_pixel(x1,y1); // Ends
D = 0; d = floor(m2n + 0.5);
x0 = x0 + 1; x1 = x1 – 1;
while (x0 < x1) {
D = D + d;
if (overflow) y0 = y0 + 1; y1 = y1 – 1
I(x0,y0) := I(x1,y1) := D div 2k-n
I(x0,y0+1) := I(x1,y1-1) := 1 - I(x0,y0)
}
Example
Work through an example (0, 0) to (5, 2)
2/5 = 0.01100110011….
€
(0, 0)
(1, 0.4)
(2, 0.8)
(3, 1.2)
(4,1.6)
(5, 2)
1, [2/5, 3/5], [4/5, 1/5], [1/5, 4/5], [3/5, 2/5], 1
x Overflow D
0 0
1 01100110011
2 11001100110
3 Overflow 00110011001
4 10011001100
5 ? 11111111111
Example
Precision of our approximation leads to errors in long lines
€
(0, 0)
(1, 0.4)
(2, 0.8)
(3, 1.2)
(4,1.6)
(5, 2)
1, [2/5, 3/5], [4/5, 1/5], [1/5, 4/5], [3/5, 2/5], 1
x Overflow D
0 0
1 01100110011
2 11001100110
3 Overflow 00110011001
4 10011001100
5 ? 11111111111
Example 2Work through an example (0, 0) to (6, 2)
€
I[i, f (i)⎣ ⎦] = I0 ( f (i)⎡ ⎤− f (i))
I[i, f (i)⎡ ⎤] = I0 ( f (i)⎣ ⎦− f (i))
Line WidthThese two lines have the same amount of ink
One is 40% longer
Diagonal is less dense
19
Aliasing
Ideal rasterized line should be 1 pixel wide
Choosing best y for each x (or visa versa) produces aliased raster lines
Gupta-SproullWu does not address the issue of line width
Gupta and Sproull provided a way to sample
Earlier than Wu's algorithm
Can deal with arbitrary line widths
Provide lookup table to compute the samples quickly
Not as fast as Wu’s algorithm
Idea: a low pass filter
Gupta-SproullProblem: Wu does not address the issue of line width
Gupta and Sproull provide a way to sample
Can deal with arbitrary line widths
Provide a way to compute the samples quickly
Sample using a cone with radius 1, volume 1
Filter: Signal strength is proportional to the volume below cone above the line
Uses lookup table to speed up computation
Use approximate distance to line
21
Polygon Aliasing
Aliasing problems can be serious for polygonsJaggedness of edges
Small polygons neglected
Need compositing so that color
of one polygon does not
totally determine color of
pixel
All three polygons should contribute to the color at pixel
Drawing Circles
Bresenham addressed the problem of drawing circles and ellipses
We deal with range shown
Slope goes from 0 to -1
Generate other 7 octants at same time
Drawing CirclesDecision Function
D(x, y) = x2 + y2 - R2
Initialize error term
e = -D(x, y)
At each step, we update x
Do we pick y, or y-1?
Update Error Term
New error term based on old
D(x, y) = x2 + y2 - R2
If we move to (x+1, y)
D(x+1, y) = D(x, y) + 2x + 1
If the next point is (x+1, y-1)
D(x+1, y-1) = D(x, y) + 2(x-y) + 2
Drawing Circlesvoid Circle( int cx, int cy, int radius ){ int x = 0, y = radius, e = 1-radius; DrawPoint( x + cx, y + cy ); while (y > x) { if (e < 0) // Go “east” e += 2*x + 3; else // Go “south-east” e += 2*(x-y) + 5; y--; x++; DrawPoint( x + cx, y + cy ); }}
12
Polygon Scan Conversion
Scan Conversion = Fill
How to tell inside from outside
Convex easy
Non-simple curves are difficult
Odd even testCount edge crossings
Winding numberodd-even fill
13
Winding Number
winding number = 2
winding number = 1
13
Winding Number
winding number = 2
winding number = 1
13
Winding Number
Count clockwise encirclements of point
Alternate definition of inside: inside if winding number ≠ 0
winding number = 2
winding number = 1
13
Scan Lines
Sort vertices by x value
Interpolate between left and right endpoints of scan line
Sometimes a scan line intersects an odd number
Count max or min vertex twice – coming and going
Count ordinary vertex once
18
Data Structure
13
Edges
Sort vertices by y value (height)
Keep list of current edges hitting this scan line
Move to next scan line
A new vertex forces us to add new edge and/or drop old edge
Keep intersections sorted by x
Interpolate across scan line
17
Scan Line Fill
Can also fill by maintaining a data structure of all intersections of polygons with scan lines
Sort by scan line
Fill each span
vertex order generated by vertex list desired order
14
Filling in the Frame Buffer
Fill at end of pipeline
Convex Polygons only
Nonconvex polygons assumed to have been tessellated (see example on prior page for why)
Shades (colors) have been computed for vertices (Gouraud shading)
Combine with z-buffer algorithmMarch across scan lines interpolating shadesIncremental work small
15
Using Interpolation
span
C1
C3
C2
C5
C4scan line
C1 C2 C3 specified by glColor or by vertex shadingC4 determined by interpolating between C1 and C2
C5 determined by interpolating between C2 and C3
interpolate between C4 and C5 along span
23
Resources
A number of papers posted on iSite
Bresenham through Program Transformations - Sproull
Line Drawing, Leap Years, and Euclid – Harris
Fast Line Scan Conversion – Rokne
A New Concept and Method for Line Clipping – Liang and Barsky
An Efficient Antialiasing Technique – Wu
Hugo Elias - http://freespace.virgin.net/hugo.elias/graphics/x_main.htm
13
Summary
Rasterizing is an important problem
Thousands of vertices, millions of fragments
Must be done quickly, and accurately
We have seen a number of clever algorithms
Focus on what we can do quickly
Integer operations on simple data