Presentation is loading. Please wait.

Presentation is loading. Please wait.

Joshua Barczak* CMSC 435 UMBC

Similar presentations


Presentation on theme: "Joshua Barczak* CMSC 435 UMBC"— Presentation transcript:

1 Joshua Barczak* CMSC 435 UMBC
Rasterization Joshua Barczak* CMSC 435 UMBC *Featuring figures by Dr. Marc Olano

2 Object-Order Rendering
Object-Space Primitives World-space Primitives Camera-Space Primitives Clip-Space Primitives Clip Modeling XForm Viewing XForm Projection XForm Clip-Space Primitives Rasterize Window XForm Viewport XForm Displayed Pixels Pixels Raster-Space Primitives We are here

3 Viewing Transform The job of the viewing transform is:
Get us from these axes Onto these axes

4 Projection Transform The job of the projection transform is:
Cram the visible universe into a unit box Project

5 Canonical View Volume (GL)
(-1,1,1) (1,1,1) Top Edge of Screen (0,1,-1) Center of screen Left Edge of Screen (0,0,-1) (-1,0,-1) (1,0,-1) (1,-1,1) Points outside the cube are not visible… (1,-1,-1) (0,-1,-1) D3D uses z=0. I like theirs better… Bottom Edge of Screen

6 Rasterization “Raster”-ize
Convert from geometric shape to set of covered pixels Also called: Scan conversion, filling Or just “drawing”

7 Our Pixel Coordinate System
0,0 Width 1 0.5,0.5 1 Height

8 Line Drawing Given endpoints of line, which pixels to draw? 8

9 Line Drawing Given endpoints of line, which pixels to draw? 9

10 Line Drawing Always step over Step up if midpoint is below line
One pixel per row/column Step up if midpoint is below line F(x,y) < 0 Use implicit line equation x1 Midpoint x0

11 Line Drawing Assume one pixel per column (x index), which row (y index)? Choose based on relation of line to midpoint between candidate pixels ? ? ? ? 11

12 Midpoint Algorithm int xa = floor(x0); int xb = floor(x1);
int y = floor(y0); if( y0 <= y1 ) { for( int x= xa; x<=xb; x++ ){ fill(x,y); if( f(x+1.5,y+1) < 0 ) y++; } } else { if( f(x+1.5,y) > 0 ) y--; Assumptions: x0 <= x1 (if not, swap endpoints) |x1-x0| > |y1-y0| (if not, reverse x and y)

13 Making it Fast Let’s count flops: Inside the loop, we have:
7x Fadd/Fsub 4x Fmul 2x Int_to_float(x,y) for( int x= xa; x<=xb; x++ ){ fill(x,y); if( f(x+1.5,y+1) < 0 ) y++; } for( int x= xa; x<=xb; x++ ){ fill(x,y); d = (y0-y1)*(x+1.5) + (x1-x0)*(y+1) +x0*y1-y0*x1; if( d < 0 ) y++; }

14 Making it Fast Take out the loop invariantsWe now have: 4x Fadd/Fsub
2x Fmul 2x Int_to_float for( int x= xa; x<=xb; x++ ){ fill(x,y); d = (y0-y1)*(x+1.5) + (x1-x0)*(y+1) +x0*y1-y0*x1; if( d < 0 ) y++; } float dy = y0-y1; float dx = x1-x0; float c = x0*y1-y0*x1; for( int x= xa; x<=xb; x++ ){ fill(x,y); d = dy*(x+1.5)+dx*(y+1)+c; if( d < 0 ) y++; } A good compiler will do this for you…

15 Making it Fast Now do some algebra Exposes more invariants…
float dy = y0-y1; float dx = x1-x0; float c = x0*y1-y0*x1; for( int x= xa; x<=xb; x++ ){ fill(x,y); d = dy*(x+1.5)+dx*(y+1)+c; if( d < 0 ) y++; } Now do some algebra Exposes more invariants… float dy = y0-y1; float dx = x1-x0; float c = x0*y1-y0*x1; for( int x= xa; x<=xb; x++ ){ fill(x,y); d = dy*x + dx*y + 1.5*dy + dx + c; if( d < 0 ) y++; } A compiler is less likely to do this for you…

16 Making it Fast This ‘d’ variable depends only on x,y
All its other inputs are loop-invariant x,y are only ever incremented When x changes, add dy. When y changes, add dx float dy = y0-y1; float dx = x1-x0; float c = x0*y1-y0*x *dy + dx; for( int x= xa; x<=xb; x++ ){ fill(x,y); d = dy*x + dx*y + c; if( d < 0 ) y++; } dx/dy are the partial derivatives of d wrt x,y

17 Incremental Computation
Now we’re down to one measly add This is also known as a ‘DDA’ Digital difference analyzer float dy = y0-y1; float dx = x1-x0; float d = x0*y1-y0*x *dy + dx; float dxdy = dx+dy; for( int x= xa; x<=xb; x++ ){ fill(x,y); if( d < 0 ){ y++; d += dxdy; } else d += dx; I’d be very surprised if a compiler did this for you…

18 Incremental Interpolation
Let’s add colors… Interpolate them using DDA // … float drdx = (r1-r0)/(x1-x0); float drdy = (r1-r0)/(y1-y0); // ditto for g,b for( int x= xa; x<=xb; x++ ){ fill(x,y,r,g,b); if( d < 0 ){ y++; d += dxdy; r += drdx + drdy; // … g,b … } else{ d += dx; r += drdx; // … g,b, …

19 Rectangles Filling Rectangles
int i0 = ceil( x f ); // Round endpoints int i1 = ceil( x f ); int j0 = ceil( y f ); int j1 = ceil(y f ); for( int y= j0; y < j1; y++ ) // fill pixels for( int x= i0; x < i1; x++ ) fill(x,y);

20 Rectangles Filling Rectangles
int i0 = ceil( x f ); // Round endpoints int i1 = ceil( x f ); int j0 = ceil( y f ); int j1 = ceil(y f ); for( int y= j0; y < j1; y++ ) // fill pixels for( int x= i0; x < i1; x++ ) fill(x,y);

21 Rectangles Filling Rectangles
int i0 = ceil( x f ); // Round endpoints int i1 = ceil( x f ); int j0 = ceil( y f ); int j1 = ceil(y f ); for( int y= j0; y < j1; y++ ) // fill pixels for( int x= i0; x < i1; x++ ) fill(x,y);

22 Rectangles Filling Rectangles
int i0 = ceil( x f ); // Round endpoints int i1 = ceil( x f ); int j0 = ceil( y f ); int j1 = ceil(y f ); for( int y= j0; y < j1; y++ ) // fill pixels for( int x= i0; x < i1; x++ ) fill(x,y);

23 Rectangles Filling Rectangles
int i0 = ceil( x f ); // Round endpoints int i1 = ceil( x f ); int j0 = ceil( y f ); int j1 = ceil(y f ); for( int y= j0; y < j1; y++ ) // fill pixels for( int x= i0; x < i1; x++ ) fill(x,y);

24 Rounding… Rounding endpoints snaps to covered pixel grid…

25 Rounding…

26 Top-Left Rule… How we break ties is important (<, not <=)

27 Top-Left Rule… Right

28 Top-Left Rule… Wrong Overdraw!

29 Colored Rectangles Bilinear Interpolation: r0 r1 v v r2 r3 u

30 Colored Rectangles Terrible code: r0 r1
for( int y=y0; y<y1; y++ ){ for( int x=x0; x<x1; x++ ) { float u = (x+0.5)/(x1-x0); float v = (y+0.5)/(y1-y0); float r = (1-u)*( (1-v)*r0 + v*r2) u *( (1-v)*r1 + v*r3) ); fill(x,y,r); } } v v r2 r3 u

31 Colored Rectangles Terrible code: r0 r1
for( int y=y0; y<y1; y++ ){ for( int x=x0; x<x1; x++ ) { float u = (x+0.5)/(x1-x0); float v = (y+0.5)/(y1-y0); float r = (1-u)*( (1-v)*r0 + v*r2) u *( (1-v)*r1 + v*r3) ); fill(x,y,r); } } v v Move invariants… r2 r3 u

32 Colored Rectangles Better code: r0 r1
for( int y=y0; y<y1; y++ ){ float v = (y+0.5) / (y1-y0); float rv0 = (1-v)*r0 + v*r2; float rv1 = (1-v)*r1 + v*r3; for( int x=x0; x<x1; x++ ) { float u = (x+0.5)/(x1-x0); float r = (1-u)*rv0 + u*rv1 fill(x,y,r); } } v v r2 r3 Convert lerps to DDAs… u

33 Colored Rectangles Much better code: r0 r1
float drdy0 = (r2-r0)/(y1-y0); float drdy1 = (r3-r1)/(y1-y0); float rv0 = r *drdy0; float rv1 = r *drdy1; for( int y=y0; y<y1; y++ ){ float drdx = (rv1-rv0)/(x1-x0); float r= rv *drdx; for( int x=x0; x<x1; x++ ) { fill(x,y,r); r += drdx; // inner DDA } rv0 += drdy0; rv1 += drdy1; // outer DDA } rv0 rv1 r2 r3 r

34 Triangles We’ll cover two algorithms: Span filling Barycentric

35 Span Filling Intersect scan line with triangle

36 Span Filling Fill pixels in each span…

37 Span Filling Fill pixels in each span…

38 Span Filling Fill pixels in each span…

39 Span Filling Fill pixels in each span…

40 Span Filling Fill pixels in each span…

41 Span Filling Fill pixels in each span…

42 Span Filling Fill pixels in each span…

43 Triangles Incremental span filling DDA down “active edges”
Snap and fill for each line DDA vertex data as we go /// Approximate code… for( y=y0; y<y1; y++ ) { for( x = round(x0); x < round(x1); x++ ) fill(x,y); x0 += dxdy0; x1 += dxdy1; }

44 Barycentric Rasterization
Start with bounding box…

45 Barycentric Rasterization
Snap to grid…

46 Barycentric Rasterization
Barycentric tests…

47 Barycentric Rasterization
Barycentric tests…

48 Barycentric Rasterization
Barycentric tests…

49 Barycentric Rasterization
Triangle Edge Equations: x1,y1 x2,y2 x0,y0

50 Barycentric Rasterization
g=1 Divide through by opposite vert: Barycentric coords. x1,y1 b=0 a=0 g=0 x2,y2 x0,y0 a=1 b=1 Point is in triangle when all three are positive

51 Barycentric Rasterization
// conservative bounding box for triangle // (snapped to pixel grid) int ymin = floor( min(y0,y1,y2) ); int ymax = ceil( max(y0,y1,y2) ); int xmin = floor( min(x0,x1,x2) ); int xmax = ceil( max(x0,x1,x2) ); // normalized edge equation: // f01(x,y) = a01*x +b01*y + c01; float a01 = (y0-y1); float b01 = (x1-x0); float c01 = (x0*y1-y0*x1); float n01 = a01*x2 + b01*y2 + c01; a01 /= n01; b01 /= n01; c01 /= n01; // similar setup for f12, f20... // Walk bounding box and test pixels for( int y=ymin; y<ymax; y++ ){ for( int x=xmin; x<xmax; x++ ){ float a = a01*(x+0.5) + b01*(y+0.5) + c01; float b = a12*(x+0.5) + b12*(y+0.5) + c12; float c = a20*(x+0.5) + b20*(y+0.5) + c20; if( a>0 && b>0 && c>0 ) fill(x,y); } g=1 x1,y1 b=0 a=0 g=0 x2,y2 x0,y0 a=1 b=1

52 Barycentric Rasterization
// Walk bounding box and test pixels for( int y=ymin; y<ymax; y++ ){ for( int x=xmin; x<xmax; x++ ){ float a = a01*(x+0.5) + b01*(y+0.5) + c01; float b = a12*(x+0.5) + b12*(y+0.5) + c12; float c = a20*(x+0.5) + b20*(y+0.5) + c20; if( a>0 && b>0 && c>0 ) fill(x,y); } g=1 x1,y1 b=0 a=0 // incremental version: float ya= c01 + (ymin+0.5)*b01 + (xmin+0.5)*a01; float yb= c12 + (ymin+0.5)*b12 + (xmin+0.5)*b12; float yc= c20 + (ymin+0.5)*b20 + (xmin+0.5)*b20; for( int y=ymin; y<ymax; y++ ){ float a = ya; float b = yb; float c = yc; for( int x=xmin; x<xmax; x++ ){ if( a>0 && b>0 && c>0 ) fill(x,y); a += a01; b += a12; c += a20; } ya += b01; yb += b12; yc += b20; g=0 x2,y2 x0,y0 a=1 b=1

53 Barycentric Interpolation
Weight per-vertex values by barycentric coordinates

54 Barycentric Rasterization
Top-Left Rule: Book says: Test an arbitrary point -1,1

55 Barycentric Rasterization
Top-Left Rule: I say: “Down and to the right” Use inward facing edge normal… Tie goes to edge if: (X==0 && y<0) || X>0

56 Pros and Cons Span filling: Barycentric Less per-pixel math
Hits only visible pixels Barycentric Simpler More parallelism Irregular sampling easier

57 Barycentric Rasterization
SIMD Parallelism (NxN Stamp)

58 Barycentric Rasterization
SIMD Parallelism (NxN Stamp)

59 Barycentric Rasterization
SIMD Parallelism (NxN Stamp)

60 Barycentric Rasterization
SIMD Parallelism (NxN Stamp)

61 Barycentric Rasterization
SIMD Parallelism (NxN Stamp)

62 Barycentric Rasterization
SIMD Parallelism (NxN Stamp)

63 Combining Ideas Problem: Lots of tests are wasted ½ to 2/3

64 Combining Ideas One Solution: Combine ideas
Conservative tile walk using DDA

65 Combining Ideas DDA between rows, snapped to tile grid
Fill tile spans with NxN stamps

66 Combining Ideas DDA between rows, snapped to tile grid
Fill tile spans with NxN stamps

67 Combining Ideas DDA between rows, snapped to tile grid
Fill tile spans with NxN stamps

68 Combining Ideas DDA between rows, snapped to tile grid
Fill tile spans with NxN stamps

69 Combining Ideas DDA between rows, snapped to tile grid
Fill tile spans with NxN stamps

70 Combining Ideas Could skip tests on the interior Fill complete block
*Bottom ones are red because I can’t assume a horizontal edge

71 Recursive Descent Subdivide screen* For a real example, read:
*Maybe better to subdivide triangle AABB instead, but this this box works better for illustration… For a real example, read: Abrash,M. “Rasterization on Larrabee” Dr. Dobbs, May 2009

72 Recursive Descent Subdivide screen For a good time, read:
Abrash,M. “Rasterization on Larrabee” Dr. Dobbs, May 2009

73 Recursive Descent …trivial reject empty nodes… For leet skillz, read:
Abrash,M. “Rasterization on Larrabee” Dr. Dobbs, May 2009

74 Recursive Descent …trivial accept full nodes…
To learn some magic, read: Abrash,M. “Rasterization on Larrabee” Dr. Dobbs, May 2009

75 Recursive Descent …keep going…
…switch to NxN stamps once they’re small enough DANGER! patent exposure in: Abrash,M. “Rasterization on Larrabee” Dr. Dobbs, May 2009


Download ppt "Joshua Barczak* CMSC 435 UMBC"

Similar presentations


Ads by Google