Navigation: back up next notes exercises
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
}
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.
What algorithms might one use to generate a colour-map?
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
A preliminary step to drawing lines and curves is choosing a suitable representation for them. There are three possible choices which are potentially useful.
| line | ![]() |
| circle | ![]() |
| line | ![]() |
| circle | ![]() |
| line | ![]() |
| circle | ![]() |
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.
|
|
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) );
}
}
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 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
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;
}
}
}
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
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.
We want to draw 2D triangle with 2D points p0, p1, and p2 in screen coordinates.

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
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) Develop an integer-only algorithm for rasterizing a circle C centered at (0,0) and of radius r, where r is an integer.
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:
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.
Clipping a polygon P to a rectangular window yields a new polygon P, which may have a more or less vertices than P.
|
|