CSC 418 - Notes
Topic 1: Introduction, Display Technology, and Basic Drawing

Navigation: back up next notes exercises

Key Concepts & Readings

OpenGL

My first Opengl Program

An OpenGL program that draws a colorful, rotating triangle. We use Glut library to setup gui and user interactions with the OpenGL program.

#include <stdio.h>
#include <GL/glut.h>
#include <math.h> 

float angle = 0; 

void draw_scene()
{
 // setup the projection matrix
 glMatrixMode( GL_PROJECTION );
 glLoadIdentity();
 
 
 // setup the modelview matrix
 glMatrixMode( GL_MODELVIEW );
 glLoadIdentity();
 glRotatef(angle,0,1,0); // rotate by angle about  y axis  // clear the color buffer - erase  the scene
 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
 // draw a triangle into the buffer
 glBegin( GL_TRIANGLES );
 glColor3f(1,0,0); // set vertex 0 color to be  red (R,G,B)
 glVertex3f( 0.0f, 0.5f, 0.0f ); // set vertex  0 coordinate to be (0,0.5,0)
 glColor3f(0,1,0);
 glVertex3f( -0.5f, -0.5f, 0.0f );
 glColor3f(0,0,1);
 glVertex3f( 0.5f, -0.5f, 0.0f );
 glEnd(); // double buffering to avoid flicker
 glutSwapBuffers();
} 

void idle()
{
 // increment the angle
 angle += 0.50;
 
 // tell the opengl machinery to redraw the scene
 glutPostRedisplay();
} 

void keyhit(unsigned char key, int x, int y)
{
 switch(key) {
 case 'q':
 exit(0); 
 }
} 

int main(int argc, char **argv)
{
 // create window and rendering context
 glutInit( &argc, argv );
 glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
 glutInitWindowSize( 640, 480 );
 glutCreateWindow( "openGLDemo" );
 
 // specify callback functions
 glutDisplayFunc(draw_world);
 glutIdleFunc(idle);
 glutKeyboardFunc(keyhit);
 
 // enable z-buffering 
 glEnable(GL_DEPTH_TEST); // pass control over  to GLUT
 glutMainLoop();
 return 0; // never reached
}

Points, Lines, and Polygons in OpenGL

Specifying vertices

  glVertex2*(...);
  glVertex3*(...);
  glVertex4*(...);

Drawing points

  GLfloat v1[] = {1.0,1.0,0.0};
  glBegin(GL_LINES);
  glVertex3v(v1); /* draws a point at v1=(1,1,0) */
  glEnd();

Function glPointSize(...) can be used to control the size of the rendered point.

Drawing lines

  GLfloat v1[] = {0.0,0.0,0.0};
  GLfloat v2[] = {1.0,1.0,1.0};
  GLfloat v3[] = {1.0,1.0,1.0};
  GLfloat v4[] = {1.0,2.0,1.0};
  glBegin(GL_LINES);
  glVertex3v(v1); glVertex3f(v2); /* line 1 with end points v1 and v2 */
  glVertex3v(v3); glVertex3f(v4); /* line 2 with end points v3 and v4 */
  glEnd();

Drawing a series of connected line segments

  GLfloat v1[] = {0.0,0.0,0.0};
  GLfloat v2[] = {1.0,1.0,1.0};
  GLfloat v3[] = {1.0,2.0,1.0};
  glBegin(GL_LINE_STRIP);
  glVertex3v(v1); glVertex3v(v2); glVertex3v(v3); /* line segments v1->v2->v3. */
  glEnd();

Drawing a series of connected line segments with an additiional segment from the last to the first vertex

  GLfloat v1[] = {0.0,0.0,0.0};
  GLfloat v2[] = {1.0,1.0,1.0};
  GLfloat v3[] = {1.0,2.0,1.0};
  glBegin(GL_LINE_STRIP);
  glVertex3v(v1); glVertex3v(v2); glVertex3v(v3); /* line segments v1->v2->v3->v1 */
  glEnd();

The following functions can be used to setup line-drawing properties

glLineWidth();

sets line width

glLineStipple();

draws a line using a stipple pattern. use glBegin(GL_LINE_STIPPLE) to enable line stippling.

Drawing a Polygon

  glBegin(GL_POLYGON);
  glVertex3v(v1); glVertex3v(v2); glVertex3v(v3); glVertex3v(v4); /* polygon with vertieces v1, v2, v3, and v4
  glEnd();

Drawing a Triangle

  glBegin(GL_TRIANGLES);
  glVertex3v(v1); glVertex3v(v2); glVertex3v(v3); /* triangle with vertices v1, v2, and v3 */
  glVertex3v(v4); glVertex3v(v5); glVertex3v(v6); /* triangle with vertices v4, v5, and v6 */
  glEnd();
 

Other arguments for glBegin() are GL_POINTS, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS, GL_QUAD_STRIP.

Valid commands between glBegin() and glEnd() are:

glVertex*()

set vertex coordinates

OpenGL, The Red Book c. 2

glColor*()

set current color

OpenGL, The Red Book c. 5

glIndex*()

set current color index

OpenGL, The Red Book c. 5

glNormal*()

set normal vector coordinates

OpenGL, The Red Book c. 2

glEvalCoord*()

generate coordinates

OpenGL, The Red Book c. 11

glCallList(), glCallLists()

execute display list(s)

OpenGL, The Red Book c. 4

glTexCoord*()

set texture coordinates

OpenGL, The Red Book c. 9

glEdgeFlag*()

control drawing of edges

OpenGL, The Red Book c. 2

glMaterial*()

set material properties

OpenGL, The Red Book c. 6

By default OpenGL draws polygons as filled faces. Use glPolygonStipple() to fill a polygon with a 32-bit by 32-bit window-aligned stipple pattern.

Use glEnable(GL_POLYGON_STIPPLE)/glDisable() to enable/disable polygon stippling.

Notes

Introduction

Applications

History

Display Technology

History

Video Raster Graphics

virtual raster device

gamma correction

Definitions

Pixel aspect ratio
width / height: usually 1
Image aspect ratio
m/n: 4/3 for NTSC, 16/9 for HDTV
Refresh rate
NTSC: 30Hz (interlaced)
PAL, SECAM: 25Hz (interlaced)
most displays: 60 or 72Hz non-interlaced
film?
 
 

Basic display architecture

Pixels

Colour maps

Colour maps are commonly employed to reduce the memory requirements for the framebuffer. Desired RGB display colours are numbered and stored in the corresponding row of the colour map. The framebuffer need only store the colour numbers in this way. The compromise is that the number of simultaneously displayable colours is limited.

What algorithms might one use to generate a colour-map?

Halftoning

Many screens and printers produce are capable of producing only black or white. Nevertheless, one would like to be able to display approximations of continuous-tone images on these devices. A solution is available by relying on the spatial integration that our eyes perform.

The following image is an example of the use of dithering to create an approximation of a continuous-tone image.


Napoleon Visual by www.PDImages.com

Line Drawing

Representations for Lines and Curves

A preliminary step to drawing lines and curves is choosing a suitable representation for them. There are three possible choices which are potentially useful.

Explicit: y = f(x)
line
circle
Parametric:   x = f(t),   y = f(t)
line
circle
Implicit:  f(x,y) = 0
line
circle

Optimal Line Drawing

Drawing lines on a raster grid implicitly involves approximation. The general process is called rasterization or scan-conversion. What is the best way to draw a line from the pixel (x1,y1) to (x2,y2)? Such a line should ideally have the following properties.

  • straight
  • pass through endpoints
  • smooth
  • independent of endpoint order
  • uniform brightness
  • brightness independent of slope
  • efficient
A Straightforward Implementation
DrawLine(x1,y1,x2,y2)
int x1,y1,x2,y2;
{
  float y;
  int x;

  for (x=x1; x<=x2; x++) {
    y = y1 +  (x-x1)*(y2-y1)/(x2-x1)
    SetPixel(x, Round(y) );
  }
}
A Better Implementation
DrawLine(x1,y1,x2,y2)
int x1,y1,x2,y2;
{
  float m,y;
  int dx,dy,x;

  dx = x2 - x1;
  dy = y2 - y1;
  m = dy/dx;
  y = y1 + 0.5;
  for (x=x1; x<=x2; x++) {
    SetPixel(x, Floor(y) );
    y = y + m;
  }
}

The Bresenham's (Midpoint) Algorithm

The midpoint algorithm is even better than the above algorithm in that it uses only integer calculations. It treats line drawing as a sequence of decisions. For each pixel that is drawn, the next pixel will be either E or NE, as shown below.

The midpoint algorithm makes use of the the implicit definition of the line, F(x,y) = 0. The E/NE decisions are made as follows.

define

if E is chosen,

if NE is chosen,

The process repeats, stepping along x, making decisions whether to set E or NE pixel.

Initialization

For an integer-only algorithm. Define

Then, the following algorithm produces the desired results for lines having x1 less than x2 and a slope less or equal to 1.
drawline(x1, y1, x2, y2, colour)
int x1, y1, x2, y2, colour;
{
  int dx, dy, d, incE, incNE, x, y;

  dx = x2 - x1;
  dy = y2 - y1;
  d = 2*dy - dx;
  incE = 2*dy;
  incNE = 2*(dy - dx);
  y = y1;
  for (x=x1; x<=x2; x++) {
    setpixel(x, y, colour);
    if (d>0) {
      d = d + incNE;
      y = y + 1;
    } else {
      d = d + incE;
    }
  }
}

Polygons

Different types of polygons:

Triangles are often particularly nice to work with because they are always planar and simple convex.

A variety of polygon representations can be used, one of the most common ones being an ordered list of references to a vertex list. This avoids redundant storage and redundant computations. We'll also be associating a variety of other information with vertices, such as normals, colours, and texture coordinates.

Modeling a square using polygonal faces

Polygon Triangulations

High-speed rendering typically relies on polygonal and curved surfaces being subdivided into triangles that can be handled efficiently by the graphics hardware. Triangles are the simplest polygons and they are the foundation of modern realtime graphics, and are by far the most popular rendering primitive.

Triangle Rasterization

We want to draw 2D triangle with 2D points p0, p1, and p2 in screen coordinates.

2-Step Procedure

Filling in the triangle

Polygon Clipping

The Sutherland-Hodgman algorithm can be used to clip any polygon (convex or concave) against any convex clipping polygon. The algorithm clips against one edge at a time, producing a new vertex list each time. The following figure assumes the most common case, a rectangular clipping window.

The algorithm can be summarized as follows:

  for each side of clipping window
     for each edge of polygon
        output points based upon the following table
Example
Using Outcodes for Trivial Accept and Reject

In many cases, two trivial tests can be used to quickly determine whether a polygon is completely inside or outside the viewing window. This then allows us to skip the above clipping procedure.  The trivial tests require first computing outcodes

A vertex outcode consists of four bits: TBRL, where:

Trivial accept:    all vertices are inside (all outcodes are 0000)
Trivial reject:     all vertices are outside with respect to any given side(bitwise AND is not 0000)

Exercises

Exercise 1

Develop an integer-only algorithm for rasterizing a circle C centered at (0,0) and of radius r, where r is an integer.

Exercise 2

Write programs to determine whether a point is inside a polygon. For simplicity, assume the test point is the origin (0,0). The programs should output the word "inside" or "outside", and should expect the following inputs:

  1. n, the number of vertices in the polygon.
  2. n pairs of numbers, each pair being the coordinates of a polygon vertex.

Use the Jordan Curve theorem: The test point is inside the curve iff an infinite ray from the point crosses the boundary an odd number of times. For simplicity, let the ray be the positive x-axis.

Exercise 3

Clipping a polygon P to a rectangular window yields a new polygon P, which may have a more or less vertices than P.

Exercise 4

  1. Use the Sutherland-Hodgman algorithm to clip this polygon on this rectangular window:
    Vertex x y
    1 50 80
    2 250 150
    3 50 220
    4 210 150
    Clip Line Value
    B y=100
    T y=200
    L x=0
    R x=200

    Clip the polygon in the following order: T,L,B,R, and list the vertices of the intermediate polygon after each pass.
  2. What shortcomings in the algorithm are evident? Illustrate with an example. How can you overcome them?