Syllabus   Videos Homework   Quizzes  
Notes   Labs   Scores   Blank


Lecture Notes
Dr. Tong Yu, Sept. 2013
All the materials presented here are adopted from the textbook and the listed references.
    1. Introduction
    2. Line Drawing
    3. Drawing Objects
    4. More Drawing Tools
    5. Vertex Array and Vertex Buffer Object
    6. Normal Vectors and Polygonal Models of Surfaces
    7. Viewing I -- Affine Transformations
    8. Viewing II -- Projections
    9. Color
    10. Lighting
    11. Blending, antialiasing, fog ..
    12. Display Lists, Bitmaps and Images
    13. Texture Mapping
    13. OpenGL Shading Language ( GLSL )
    Videos

    Line Drawing
    1. Bresenham's Line Algorithm

    2. Assume: y = mx + b
       

    3. Given two endpoints ( x0, y0 ), ( xn, yn ) we can choose the start point ( xk, yk )
    4. We want to decide what's the next pixel to draw; we have eight choices. ( Why? )
    5. Assume 0 ≤ m ≤ 1 and x0 < xn
      • Our choices are either ( xk + 1, yk ) or ( xk + 1, yk + 1 )

      • Let
        dlower = y - yk
          = m ( xk + 1 ) + b - yk
        and
        dupper = ( yk + 1 ) - y
          = yk + 1 - m ( xk + 1 ) - b
      • To determine which one is closer to the line path:
        dlower - dupper = 2m ( xk + 1 ) - 2 yk + 2b - 1

        Let m = ( yn - y0 ) / ( xn - x0 ) = Δy / Δx

        Define the decision parameter as

        pk = Δx ( dlower - dupper )         (pk negative, choose lower; pk positive, choose upper)
          = 2Δy.xk - 2Δx.yk + c     ----- ( 1 )
        where c = 2Δy + Δx ( 2b - 1 ) is a constant ( independent of pixel position )

        Therefore,

        pk+1 - pk = 2Δy ( xk+1 - xk ) - 2Δx ( yk+1 - yk ) But, xk+1 = xk + 1 So, pk+1 = pk + 2Δy - 2Δx ( yk+1 - yk )     ---- ( 2 ) with p0 = 2Δy - Δx

        In ( 2 ) , yk+1 - yk is either 0 or 1, depending on the sign of pk. From ( 1 ), as Δx >0, if the pixel at yk is closer to the line path than at yk + 1 (i.e. dlower < dupper ), pk is negative and we choose the next pixel to be the lower pixel; otherwise we choose the upper pixel.

      Brensenham's Line Drawing algorithm for |m| < 1

      1. Input two endpoints ( x0, y0 ), ( xn, yn ) where ( x0, y0 ) is the left endpoint.
      2. Plot ( x0, y0 ) as first point.
      3. Calculate Δx, Δy and p0 = 2Δy - Δx
      4. Start with k = 0, perform the test:
        If pk < 0, the next point to plot is ( xk +1, yk ) and pk+1 = pk + 2 Δy
        otherwise, the next point to plot is ( xk +1, yk + 1) and pk+1 = pk + 2 Δy - 2 Δx
      5. Perform step 4     Δx - 1 times.

    6. Sample Implementation:
      //bline.cpp : Bresenham Line algorithm, works only for |m| < 1
      
      #include <GL/glut.h>
      #include <stdio.h>
      #include <math.h>
      
      void init(void)
      {
        glClearColor(1.0,1.0,1.0,0.0);
        glMatrixMode(GL_PROJECTION);
        gluOrtho2D(0.0,400.0,0.0,400.0);
      }
      
      void setPixel(GLint x,GLint y)
      {
        glBegin(GL_POINTS);
           glVertex2i(x,y);
        glEnd();
      }
      
      void line()
      {
        int x0 = 50, y0=50, xn = 300, yn = 150, x, y;
        int	dx, dy,		//deltas
      	pk,		//decision parameter
        	k;		//looping variable
      
        glClear(GL_COLOR_BUFFER_BIT);
        glColor3f( 1 ,0, 0);  
        setPixel(x0, y0);	//plot first point
        
        // difference between starting and ending points
        dx = xn - x0;
        dy = yn - y0;
        pk = 2 * dy - dx; 
        x = x0;	y = y0; 
        
        for ( k = 0; k < dx-1; ++k ) {
          if ( pk < 0 ) {
            pk = pk + 2 * dy;			//calculate next pk
      					//next pixel: (x+1, y )
          } else {
            					//next pixel: (x+1, y+1)
            pk = pk + 2*dy - 2*dx;		//calculate next pk
            ++y;
          }
          ++x;
          setPixel( x, y );
        }
      
        glFlush();
      }
      
      int main(int argc,char **argv){
          glutInit(&argc,argv);
          glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
          glutInitWindowPosition(0,0);
          glutInitWindowSize(500,500);
          glutCreateWindow("Bresenham Line");
          init();
          glutDisplayFunc( line );
          glutMainLoop();
          return 0;
      }
      
        
    7. Bresenham's Circle Algorithm

    8. Only has to consider one eigth of a circle, other parts being symmetric.
    9. x2 + y2 = r2

    10. Compute the relative error for each of the possible choices ( xk+1, yk ) and ( xk+1, yk - 1 )

    11. Error for P1:

        E1(k) = [yk2 - y2]
          = yk2 + ( xk + 1 )2 - r2

    12. Error for P2:

        E2(k) = y2 - (yk - 1)2
          = r2 - ( xk + 1 )2 - (yk - 1)2

    13. Consider

        dk = ( E1(k) - E2(k) ) / 2 = yk2 + xk2 + 2xk - yk + c
      where c = 3/2 - r2 is a constant.

    14. If dk < 0 ( i.e. P1 nearer to curve ), pick P1 as next pixel:
        yk+1 = yk, and
        dk+1 = yk2 + (xk + 1)2 + 2( xk + 1 ) - yk + c
          = yk2 + xk 2 + 2xk + 1 + 2xk + 2 - yk + c
          = dk + 2xk + 3

    15. If dk > 0 ( i.e. P2 nearer to curve ), pick P2 as next pixel:
        yk+1 = yk - 1, and
        dk+1 = (yk - 1) 2 + (xk + 1)2 + 2( xk + 1 ) - (yk-1) + c
          = yk2 - 2yk + 1 + xk2 + 2xk + 1 + 2xk + 2 - (yk-1) + c
          = dk + 2 (xk - yk) + 5

    16. The initial point is ( 0, r ), so we can set d0 = r2 + 02 + 2x0 - r + c = 3/2 - r

    17. Sample Implementation:
      //bcircle.cpp : Bresenham Circle algorithm
      
      #include <GL/glut.h>
      #include <stdio.h>
      #include <math.h>
      
      void init(void)
      {
        glClearColor(1.0,1.0,1.0,0.0);
        glMatrixMode(GL_PROJECTION);
        gluOrtho2D(0.0,200.0,0.0,200.0);
      }
      
      void setPixel(GLint x,GLint y)
      {
        glBegin(GL_POINTS);
           glVertex2i(x,y);
        glEnd();
      }
      
      void Circle(){
      	
        int xCenter=100,yCenter=100,r=50;
        int x=0,y=r;
        int d = 3/2 - r;				// = 1 - r
        glClear(GL_COLOR_BUFFER_BIT);
        glColor3f( 1 ,0, 0);  
        while(x<=y){
          setPixel(xCenter+x,yCenter+y);
          setPixel(xCenter+y,yCenter+x);		//find other points by symmetry
          setPixel(xCenter-x,yCenter+y);
          setPixel(xCenter+y,yCenter-x);
          setPixel(xCenter-x,yCenter-y);
          setPixel(xCenter-y,yCenter-x);
          setPixel(xCenter+x,yCenter-y);
          setPixel(xCenter-y,yCenter+x);
      
          if (d<0)
       	d += (2*x)+3;
          else {
      	d += (2*(x-y))+5;
      	y -= 1;
          }
          x++;
        }
      
        glFlush();
      }
      
      int main(int argc,char **argv){
          glutInit(&argc,argv);
          glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
          glutInitWindowPosition(0,0);
          glutInitWindowSize(500,500);
          glutCreateWindow("Bresenham Circle");
          init();
          glutDisplayFunc(Circle);
          glutMainLoop();
          return 0;
      }
      
    18. Plotting Functions

      Suppose we wish to learn the behavior of some mathematical functions f(x) as x varies. For example, how does

      f(x) = e-|x| cos ( 2π x ) behave when x varies between 0 and 4? We may plot the function using a code like:
      for ( double x = 0; x < 4.0; x += 0.005 )
        surf.lineTo ( (int) x, (int) f(x) );
      

      Problem!! What ?
    19. The picture produced will be very tiny, because the total span of x is between 0 and 4, covering only four pixels of the screen
    20. Therefore, we need to scale and position the values to be plotted so that they cover the screen window appropriately
    21. Scaling x
        sx = x * VWIDTH / 4.0;
      sx = 0, when x = 0; sx = VWIDTH, when x = 4.0
    22. Scaling and translating y
      In the example, -1 ≤ y ≤ 1; we want sy = 0, when y = 1, and sy = VHEIGHT, when y = -1; so we set
        sy = ( -y + 1 ) * VHEIGHT / 2.0;
    23. The scaling and translation can be expressed in the form
        sx = a * x + c
        sy = b * y + d
      or in matrix form
        sx
        sy
        1
        = a   0   c
        0   b   d
        0   0   1
        x
        y
        1
      In our example a = VWIDTH / 4.0, c = 0; b = -VHEIGHT / 2.0, d = VHEIGHT / 2.0