Triangle Rasterization-Computer Graphics-Lecture Notes, Study notes of Computer Graphics

Computer Graphics involves technology to accept, process, transform and present information in a visual form that also concerns with producing images and animations using a computer. This course teach how to make your own design in computer using OpenGl. This lecture includes: Triangle, Rasterization, Introduction, Solid, Fill, Rendering, Performance, Optimization, Important, Accuracy

Typology: Study notes

2011/2012

Uploaded on 08/04/2012

parnashi
parnashi 🇮🇳

4.4

(49)

71 documents

1 / 11

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
Lecture No.22 Triangle Rasterization
Introduction
High performance triangle rasterization is a very important topic in Computer Graphics in
today’s world.
Triangles are the foundation of modern real time graphics, and are by far the most popular
rendering primitive. Most computer games released in the last few years are almost
completely dependent on triangle rasterization performance. Recently the focus of
graphics performance optimization is beginning to shift to bandwidth requirements as
well as transformation and lighting. Nevertheless, rasterization performance is still a
factor, and this lecture will provide most of the basics of high performance triangle
rasterization. Also, it will go into detail about two often neglected rendering quality
improvements, sub-pixel and sub-texel accuracy. Also, smooth shading and texture
mapping techniques will be described.
Solid Fill Triangle Rendering
The first step in triangle rasterization is to be able to render a solid filled triangle. All
triangle drawing routines should fill the same pixels on the screen so it makes sense to
start with the simplest example and work up. The goal is to draw a filled triangle by
plotting pixels on the screen given three vertex points.
The first step is to sort the triangle vertices by y. Label the top vertex (x0,y0),the middle
vertex (x1,y1), and the bottom vertex (x2,y2). Now the triangle fill can be thought of as
two separate routines, filling the top half (the region between y0 and y1) and filling the
bottom half (the region between y1 and y2). Each of the fill routines consists of filling the
triangle region one scanline at a time, using the DDA algorithm to find the x values of the
beginning and the end of each pixel span to draw. The top half will uses DDA to find the
x values on edge01 and edge02. The bottom half uses DDA to find the x values on edge12
and edge02.
Sub-pixel Accuracy
The afore mentioned rasterization technique is works well when vertex coordinates are
integers, but there are some subtle changes that should be made to the DDA algorithm
when the vertex coordinates do not fall on integer bounds. In essence, sub-pixel accuracy
is a way of accounting for the fractional components of the vertex positions in the triangle
rasterizer. The changes that need to be made are mainly used to prevent jumpiness when
there are amounts of motion that are smaller than a pixel. The edges of the triangle reflect
the fractional change, and without sub-pixel accuracy, the entire triangle would jump
down a pixel at a time. Also, the calculations performed for sub-pixel accuracy allow for
quicker edge anti-aliasing.
The idea of sub-pixel accuracy is to pre-step the x coordinate of each of the edge DDAs
an amount corresponding to the fractional component of the y position of the vertex. For
docsity.com
pf3
pf4
pf5
pf8
pf9
pfa

Partial preview of the text

Download Triangle Rasterization-Computer Graphics-Lecture Notes and more Study notes Computer Graphics in PDF only on Docsity!

Lecture No.22 Triangle Rasterization

Introduction

High performance triangle rasterization is a very important topic in Computer Graphics in today’s world. Triangles are the foundation of modern real time graphics, and are by far the most popular rendering primitive. Most computer games released in the last few years are almost completely dependent on triangle rasterization performance. Recently the focus of graphics performance optimization is beginning to shift to bandwidth requirements as well as transformation and lighting. Nevertheless, rasterization performance is still a factor, and this lecture will provide most of the basics of high performance triangle rasterization. Also, it will go into detail about two often neglected rendering quality improvements, sub-pixel and sub-texel accuracy. Also, smooth shading and texture mapping techniques will be described.

Solid Fill Triangle Rendering

The first step in triangle rasterization is to be able to render a solid filled triangle. All triangle drawing routines should fill the same pixels on the screen so it makes sense to start with the simplest example and work up. The goal is to draw a filled triangle by plotting pixels on the screen given three vertex points. The first step is to sort the triangle vertices by y. Label the top vertex ( x 0 , y 0 ) , the middle vertex ( x 1 , y 1 ), and the bottom vertex ( x 2 , y 2 ). Now the triangle fill can be thought of as two separate routines, filling the top half (the region between y 0 and y 1 ) and filling the bottom half (the region between y 1 and y 2 ). Each of the fill routines consists of filling the triangle region one scanline at a time, using the DDA algorithm to find the x values of the beginning and the end of each pixel span to draw. The top half will uses DDA to find the x values on edge 01 and edge 02. The bottom half uses DDA to find the x values on edge 12 and edge 02.

Sub-pixel Accuracy

The afore mentioned rasterization technique is works well when vertex coordinates are integers, but there are some subtle changes that should be made to the DDA algorithm when the vertex coordinates do not fall on integer bounds. In essence, sub-pixel accuracy is a way of accounting for the fractional components of the vertex positions in the triangle rasterizer. The changes that need to be made are mainly used to prevent jumpiness when there are amounts of motion that are smaller than a pixel. The edges of the triangle reflect the fractional change, and without sub-pixel accuracy, the entire triangle would jump down a pixel at a time. Also, the calculations performed for sub-pixel accuracy allow for quicker edge anti-aliasing.

The idea of sub-pixel accuracy is to pre-step the x coordinate of each of the edge DDAs an amount corresponding to the fractional component of the y position of the vertex. For

docsity.com

notation sake we denote the upper vertex of an edge as xa ,ya and the lower vertex as xb ,yb. For each edge the starting x coordinate for the DDA algorithm xs is obtained by a prestep amount xprestep to the original x coordinate of the vertex:

The pre step amount ‘ xf ’ for x , is calculated by multiplying  x/  y by the fix up distance, y f

. This fix up distance is just the distance of ya to the next lowest scan line. For clarification purposes, here is some pseudo code for the sub-pixel accurate DDA, which can be used to find endpoints for the pixel spans in our triangle rasterizer. This technique can be used to draw sub-pixel accurate lines also.

SubPixDDA( float xa, float ya, float xb, float yb) { int yai,ybi, /scanline range to draw/ y; /iterator for scanline/

float xp, /prestep in x / x, /current x position/ yf, /*fractional distance in y / dxdy; /amount to change x by per scanline (1/slope) */

dxdy=(xb-xa)/(yb-ya); /perform slope calculation using true / /vertex positions/ yai=ceiling(ya); ybi=ceiling(yb);

yf=yai-ya; xp=(dxdy*yf); x=xa+xp;

for(y=yai;y<ybi;y++) /iterate over scanlines/ { /*do scanline stuff using x,y */ x+=dxdy; } }

Smooth Shaded Triangle Rasterization

So far we have described a method for solid filled triangle rasterization, but there are a variety of other fill types that are use. Smooth shaded triangles can be used to approximate the effects of lighting over a surface. They can be used for light falloff, or can be used to give the appearance to a curved surface. The idea behind smooth shading is to linearly interpolate the vertex colors over the triangle being drawn. Luckily for us, we already have the tool to do this, DDA. In fact, drawing smooth shaded polygons is not much more difficult than drawing solid filled ones. The vertex colors must be interpolated along each edge of the triangle using DDA. This gives us a separate pair of colors for the beginning and end of each pixel span for

docsity.com

color c00,c01,c10,c11; int u0,u1,v0,v1; float ufrac,vfrac;

u0=floor(u); u1=ceiling(u); v0=floor(u); v1=ceiling(u); ufrac=u-u0; vfrac=v=v0;

c00=texMap[u0][v0]; c01=texMap[u0][v1]; c10=texMap[u1][v0]; c11=texMap[u1][v1];

return( vfrac * (ufracc11 + (1-ufrac)c01) + (1-vfrac) * (ufracc10 + (1-ufrac)c00) );

}

Sub-Texel Accuracy

The disparity between integer screen pixel locations and the mathematical equations for the triangle also causes problems for texture mapping, and smooth shading. Any value that is interpolated over the triangle such as r, g, and b for smooth shading and u and v for texture mapping must take into account the fractional component of the vertex information. Taking these fractional quantities into account is called sub-texel accuracy, for the reason that it is used most commonly with texture mapping. In actuality, sub-texel accuracy can be applied to any quantity interpolated over the triangle. Without sub-texel accuracy, the texture will visibly jump around by a pixel when the triangle undergoes small amounts of motion.

The sub-texel accurate DDA interpolators for texture mapping are very similar to the sub- pixel accurate DDA routine presented earlier. For each edge of the triangle, the sub-texel DDA for the interpolated values is identical to the sub-pixel DDA, when u or v is substituted for x. However, for each scan line, the beginning and end x locations of the pixel span have fractional components which need to be accounted for. To interpolate the texels coordinates correctly over the pixel span for each scan line, a subtexel accurate pixel span DDA is required. Luckily for us, this formulation is also virtually identical to the sub-pixel DDA. All that need to be done is to substitute u or v for x in the original,

and substitute x for y in the original. docsity.com

Flat Filling Triangles

Drawing triangle (or in general convex polygon, but as we discussed we will use only triangles) is very simple. The basic idea of the line triangle drawing algorithm is as follows. For each scan line (horizontal line on the screen), find the points of intersection with the edges of the triangle. Then, draw a horizontal line between intersections and do this for all scan lines. But how can we find these points quickly? Using linear interpolation!

We have 3 vertices and we want to find coordinates of all points belonging to segments determined by these vertices. Assume we have segment given by points: (xa,ya) and (xb,yb). Our task is to find points: (xc,ya+1), (xd,ya+2), ... , (xm,yb-1), (xn,yb). Notice that xa changes to xb in (yb-ya) steps.

We also have: xa=xa+0*(xb-xa)/(yb-ya),

Xb = xa + ( yb-ya ) * ( xb-xa ) / ( yb-ya ) and, in general, xi = xa + ( yi – ya ) * delta ,

where delta=(xb-xa)/(yb-ya).

The general function for linear interpolation is:

f(X) = A + X * ( (B-A) / steps) where we slide from A to B in steps steps

Here is pseudo code for a triangle filling algorithm.

The coordinates of vertices are (A. x,A. y), (B. x,B. y), (C. x,C. y); we assume that A. y <= B. y <= C. y (you should sort them first)

dx1,dx2,dx3 are deltas used in interpolation

Horizontal line draws horizontal segment with coordinates (S. x, Y), (E. x, Y)

S. x, E. x are left and right x-coordinates of the segment we have to draw

S = A means that S. x = A. x; S. y = A. y;

docsity.com

Gouraud Shading

The idea of gouraud and flat triangle is nearly the same. Gouraud takes only three parameters more (the color value of each of the vertices), and the routine just interpolates among them drawing a beautiful, shaded triangle. You can use 256-colors mode, in which vertices' colors are simply indices to palette or hi- color mode (recommended).

Flat triangle interpolated only one value (x in connection with y), 256 colors gouraud needs three (x related to y, color related to y, and color related to x), hi-color gouraud needs seven (x related to y, red, green and blue components of color related to y, and color related to x (also three components))

Drawing a gouraud triangle, we add only two parts to the flat triangle routine. The horizline routine gets a bit more complicated due to the interpolation of the color value related to x but the main routine itself remains nearly the same.

We'll give you a full gouraud routine because good pseudo code is better than the best description: the coordinates of vertices are (A.x,A.y), (B.x,B.y), (C.x,C.y) we assume that A.y<=B.y<=C.y (you should sort them first) vertex A has color (A.r,A.g,A.b), B (B.r,B.g,B.b), C (C.r,C.g,C.b), where X.r is color's red component, X.g is color's green component and X.b is color's blue component dx1,dx2,dx3 are deltas used in interpolation of x-coordinate dr1,dr2,dr3, dg1,dg2,dg3, db1,db2,db3 are deltas used in interpolation of color's components putpixel(P) plots a pixel with coordinates (P.x,P.y) and color (P.r,P.g,P.b) S=A means that S.x=A.x; S.y=A.y; S.r=A.r; S.g=A.g; S.b=A.b;

Drawing triangle:

if (B.y-A.y > 0) { dx1=(B.x-A.x)/(B.y-A.y); dr1=(B.r-A.r)/(B.y-A.y); dg1=(B.g-A.g)/(B.y-A.y); db1=(B.b-A.b)/(B.y-A.y); } else dx1=dr1=dg1=db1=0;

if (C.y-A.y > 0) { dx2=(C.x-A.x)/(C.y-A.y); dr2=(C.r-A.r)/(C.y-A.y); dg2=(C.g-A.g)/(C.y-A.y);

docsity.com

db2=(C.b-A.b)/(C.y-A.y); } else dx2=dr2=dg2=db2=0;

if (C.y-B.y > 0) { dx3=(C.x-B.x)/(C.y-B.y); dr3=(C.r-B.r)/(C.y-B.y); dg3=(C.g-B.g)/(C.y-B.y); db3=(C.b-B.b)/(C.y-B.y); } else dx3=dr3=dg3=db3=0;

S=E=A; if(dx1 > dx2) { for(;S.y<=B.y;S.y++,E.y++) { if(E.x-S.x > 0) { dr=(E.r-S.r)/(E.x-S.x); dg=(E.g-S.g)/(E.x-S.x); db=(E.b-S.b)/(E.x-S.x); } else dr=dg=db=0; P=S; for(;P.x < E.x;P.x++) { putpixel(P); P.r+=dr; P.g+=dg; P.b+=db; } S.x+=dx2; S.r+=dr2; S.g+=dg2; S.b+=db2; E.x+=dx1; E.r+=dr1; E.g+=dg1; E.b+=db1; }

E=B; for(;S.y<=C.y;S.y++,E.y++) { if(E.x-S.x > 0) { dr=(E.r-S.r)/(E.x-S.x); dg=(E.g-S.g)/(E.x-S.x); db=(E.b-S.b)/(E.x-S.x); } else dr=dg=db=0; P=S; for(;P.x < E.x;P.x++) { putpixel(P); P.r+=dr; P.g+=dg; P.b+=db; } S.x+=dx2; S.r+=dr2; S.g+=dg2; S.b+=db2; E.x+=dx3; E.r+=dr3; E.g+=dg3; E.b+=db3; } } else { for(;S.y<=B.y;S.y++,E.y++) { if(E.x-S.x > 0) { dr=(E.r-S.r)/(E.x-S.x);

docsity.com

The left triangle is the triangle which is drawn onto the screen. There's a single scanline (one call to the horizline routine) pointed out as an example. The triangle on the right is the same triangle in the bitmap space, and there's the same scanline drawn from another point of view into it, too. So we need just to interpolate, interpolate, and once more interpolate in texture filler - an easy job if you've understood the idea of gouraud filler. An optimization trick: the color deltas in gouraud and (u,v) coordinate deltas in texture remain constant, so we need to calculate them only once per polygon. Let's take the u delta in linear texturing as an example. Assume, that dx2<=dx3 (we are using the same symbols like in flat and gouraud filler). As we know, we need to interpolate S.u to E.u in the horizline routine in (S.x-E.x) steps. We are in the need of a u delta (du) which would be the same for the whole polygon. So instead of calculating in each scanline this:

du = (E.u-S.u) / (E.x-S.x), we do like this in the setup part of the polygon routine: We know that S.x = Ax + (B.y - A.y) * dx1, S.u = A.u + (B.y-A.y) * du1, E.x = B.x = A.x + (B.y-A.y) * dx2, E.u = B.u = A.u + (B.y-A.y) * du2, When y = B.y (when y is the y-coordinate of the second vertex). When we place the values of the variables S.u,E.u,S.x and E.x (above) to the u delta statement,

du = (E.u-S.u) / (E.x-S.x),

we get the following statement as a result:

_[A.u+(B.y-A.y)du2] - [A.u+(B.y-A.y)du1] du = ----------------------------------------- [A.x+(B.y-A.y)dx2] - [A.x+(B.y-A.y)dx1]_**

_(B.y-A.y)(A.u-A.u+du2-du1) du = --------------------------- (B.y-A.y)(A.x-A.x+dx2-dx1)_**

du2-du du = ------- dx2-dx

docsity.com

outerUdelta2-outerUdelta innerUdelta = -------------------------------- outerXdelta2-outerXdelta Nice! But what if dx2 = dx1? This of course means that the polygon is just one line, so du doesn't need any specific value; zero does the job very well. Note! I find it hard to get good results using fixed point math because of inadequate precision.

Environmental Mapping

As I said in 'shading' part, the way demos do environment mapping is very simple. Take the X and Y components of your pseudo-normal vectors (perpendicular to vertices), and use them to index your texture map!

Your formulae would be: U = N.x * 128 + 127 V = N.y * 128 + 127 (assuming 256x256 texture maps). Or in general U = N.x * (width / 2) + (width / 2) - 1 V = N.y * (height / 2) + (height / 2) - 1

Using texturing and shading at the same time is quite straightforward to implement: the basic idea being that we just interpolate the values of both texture and shade and blend them in a suitable ratio (alpha-blending).

docsity.com