Upload
others
View
4
Download
0
Embed Size (px)
Citation preview
1
From Ver(ces to Fragments:
Rasteriza(on
l determine fragments to be covered l interpolate attributes per fragment
From Ver(ces to Fragments
vertex shader
2D screen
fragment shader
final pixels rasterizer
fragments
3D vertices
2
• How to draw primitives? – Convert from geometric definition to pixels – Rasterization = selecting the pixels
• Will be done frequently • Must be fast:
• use integer arithmetic • use addition instead of multiplication
Rasteriza(on
This Lecture • Line-drawing algorithm
– Naïve algorithm – Bresenham algorithm
3
Scan Conver(ng 2D Line Segments • Given:
– Segment endpoints (integers x1, y1; x2, y2) • Identify:
– Set of pixels (x, y) to display for segment
(x1, y1)
(x2, y2)
Line Rasteriza(on Requirements • Transform continuous primitive into discrete samples
• Uniform thickness & brightness • Continuous appearance • No gaps • Accuracy • Speed
(x1, y1)
(x2, y2)
4
Simple Line
• Slope-intercept equation of a line:
y = mx + h
• Given (x1, y1) and (x2, y2):
• Naïve line approach: - increment x, solve for y - known as DDA (Digital Differential Analyzer)
h
(x1, y1)
(x2, y2)
m =y2 − y1x2 − x1
h = y1 −mx1
DDA Rasteriza(on Algorithm • Simply compute y as a function of x
– Move vertical scan line from x1 to x2 – Determine y in terms of x – Set pixel (x, Round (y))
x
y
(x1, y1)
(x2, y2)
y = y1+m(x − x1)
m =dydx
=y2 − y1x2 − x1
Two floating point operations per pixel !!!
Round is expensive!!!
5
Efficiency • Computing y value is expensive
• Observe: y += m at each x step (m = dy/dx) )1(1 xxmyy −+=
y(x+1)
y(x)x x+1
m
x
y(x)
(x1, y1)
(x2, y2)
y(x+1)
x+1
DDA Line Rasteriza(on
x
y(x)
(x1, y1)
(x2, y2)
y(x+1)
x+1
y(x+1)
y(x)x x+1
m
Line(x1,y1,x2,y2) { float slope, y; slope = (y2-y1)/(x2-x1); y = y1; for(x = x1; x <= x2; x++) { PlotPixel(x, Round(y)); y = y + slope; } }
One floating point operation per pixel !!!
Round is expensive!!!
6
Example
)2,0(
(6, 4)
m = 4−26−0 =
13
x = 0 y = 2 x = 1 y = 7/3 x = 2 y = 8/3 x = 3 y = 3 x = 4 y = 10/3 x = 5 y = 11/3
Does it Work?
• OK for lines with a slope of 1 or less
• NOT ok for lines with slope greater than 1: – lines become more
discontinuous in appearance – must add more than 1 pixel per
column to make it work.
• Solution? - use symmetry.
7
BeHer: Bresenham's Line Algorithm • Select pixel vertically closest to line segment
– intuitive, efficient, pixel center always within 0.5 vertically
• Same result as the DDA approach
Incremental Algorithm: - current value uses previous value - integer operations only
Bresenham's Algorithm • Observation:
– If we're at pixel P(x, y), the next pixel must be either E (x+1, y) or NE (x+1, y+1)
ENE
P
8
Bresenham Step • Which pixel to choose: E or NE? • Error associated with a pixel:
Error pixel NE
Error pixel E E
N E
• Pick the pixel with error < ½ • The sum of the 2 errors is _____
Bresenham Step • How to compute the error? • Line defined as y = mx + h • Vertical distance from line to pixel (x, y):
e(x, y) = mx+h-y – negative if pixel above L – zero on L – positive below L
e is called the error function.
e > 0
e < 0
e = 0
L
9
Bresenham's Algorithm • How to compute the error? • Error Function:
e(x, y) = mx+h-y • Initially
e(x1, y1) = 0 • On each iteration:
update x: update e: if (e ≤ 0.5): if (e > 0.5):
x' = x +1 e' = e + m y' = y (choose pixel E) y' = y +1 (choose pixel NE) e' = e - 1
e
e’
Summary of Bresenham • Initialize e = 0 • for (x = x1; x ≤ x2; x++)
– plot (x,y) – update x, y, e
• Generalize to handle all eight octants using symmetry • Still using floating point! e' = e + m • Can we use only integer arithmetic?
ENE
10
Bresenham with no Floa(ng Point • Error function e(x, y) = mx+h-y, • At selected pixel (x, y): e(x, y) <= ½ • Simplify:
2·e(x, y) – 1 <= 0 2mx + 2h – 2y – 1 <= 0
2x·dy + 2h·dx – 2y·dx – dx <= 0 (Note that h·dx = y1·dx – x1·dy is an integer)
• Define F(x,y) = 2x·dy + 2h·dx – 2y·dx – dx – If F <= 0 stay horizontal – If F > 0 move up
ENE
dxdy
xxyym =
−
−=
12
12
Bresenham with no Floa(ng Point • Define
F(x, y) = 2x·dy + 2h·dx – 2y·dx – dx
– If F <= 0 stay horizontal – If F > 0 move up
• Incremental update for next pixel: – If stay horizontal: x+=1, F += 2dy – If move up: x+=1, y+=1, F += 2(dy –dx)
ENE
11
Bresenham Line Pseudocode BresenhamLine(x1,y1,x2,y2) { int dx = x2 – x1; int dy = y2 – y1; int f = -dx; int y = y1; for(x = x1; x <= x2; x++) { if(f <= 0) f += 2*dy; else { f += 2*(dy-dx); y++; } PlotPixel(x, y); } }
Algorithm = single instruction on graphics chips!
2D Scan Conversion • Geometric primitive
– 2D: point, line, polygon, circle... – 3D: point, line, polyhedron, sphere...
• Primitives are continuous; screen is discrete
12
Use Line Rasteriza(on • Compute the boundary pixels
Scan-‐line Rasteriza(on • Compute the boundary pixels • Fill the spans
13
Next: • Anti-Aliasing
Effects of An(-‐aliasing
14
Addi(onal Benefit of An(-‐aliasing • Note: brightness can vary with slope
– What is the maximum variation? • Compensate for this with antialiasing
√2 * L
L
How do we remove aliasing? • Solution 1: Super-Sampling
– Divide pixel into “sub-pixels”: 2x 2, 3x3, 4x4, etc. – Pixel color is the average of its sub-pixel colors
Pixels Pixel Subdivision (4x4)
15
Super-‐Sampling
Pixel Subdivision
Bresenham at sub-pixel level
Each pixel can have a maximum of 4 colored sub-pixels
How many sub-pixels are colored?
0 0 0 4
2 4 4 0
2 0 0 0 Assign color
Fraction line color for the pixel
0.0 0.0 0.0 1.0
0.5 1.0 1.0 0.0
0.5 0.0 0.0 0.0
How do we remove aliasing? • Super-sampling is expensive
– Render internally at higher resolution – Invoke fragment shader once per sub-fragment – Down-sample to fit the screen resolution
• Solution 2: Multi-Sampling – Faster alternative to super-sampling – Invoke fragment shader once per fragment
16
OpenGL
glfwWindowHint(GLFW_SAMPLES, 4);!glEnable(GL_MULTISAMPLING);!
• On most OpenGL drivers, multisampling is enabled by default so this call is then a bit redundant, but it's usually a good idea to enable it anyways