
Roberto Toldo,
<nome.cognome@univr.it >
Hit the space bar for next slide
Rendering is the process of converting geometric models into a 2D picture. OpenGL is capable of rendering three types of geometric primitives: points, lines, and polygons. It can also render image and bitmap primitives, which are covered in the sequel to this course.
The geometric primitives are composed of vertices, placed in a three dimensional `world' defined in world coordinates. The vertices are defined in homogeneous coordinates, which combine world coordinates (x,y,z) with a scaling factor w.
In OpenGL, vertices are specified using the glVertex* functions. There are many forms of glVertex* for specification of 2, 3, or 4 coordinates using long or short integer types, or floating point data types. The different forms can be used in any combination when defining a primitive.
To draw a geometric primitive in OpenGL, call glBegin() with the type of primitive you wish to render. Then call the glVertex* functions to define all the vertices, and finish the primitive with a call to glEnd(). The geometric primitives may be simple (points, lines, triangles or quadrilaterals), or complex (line strips and loops, triangle strips and fans, quadrilateral strips).
When OpenGL renders a triangle strip, there are two retained vertices, R1 and R2. There is a pointer, P, which always points to the older of the two retained vertices. Here the GL_TRIANGLE_STRIP primitive is started:
glBegin (GL_TRIANGLE_STRIP);
/* P is initialized to point to R1. */
After the first two vertices, each additional vertex produces one
triangle. Here is what happens as each of the vertices are specified:
glVertex3fv (vNew);
The triangle fan is simpler. The first vertex specified is a pivot point. After the second vertex, subsequent vertices specify triangles formed by v0, the previous vertex, and the most recently specified vertex. The triangle fan can be used to draw cones, circles, and filled arcs.

| OpenGL Call | Triangle Drawn | R1 | R2 | vNew | P |
| glBegin (GL_TRIANGLE_STRIP); glVertex3fv (v0); glVertex3fv (v1); glVertex3fv (v2); glVertex3fv (v3); glVertex3fv (v4); glVertex3fv (v5); glVertex3fv (v6); glEnd(); glBegin (GL_TRIANGLE_FAN) glVertex3fv (v6); glVertex3fv (v5); glVertex3fv (v7); glVertex3fv (v8); glVertex3fv (v9); glVertex3fv (v10); glEnd(); |
0, 1, 2 2, 1, 3 2, 3, 4 4, 3, 5 4, 5, 6 6, 5, 7 6, 7, 8 6, 8, 9 6, 8, 10 |
v0 v0 v2 v2 v4 v4 v6 |
v1 v1 v3 v3 v5 v5 |
v0 v1 v2 v3 v4 v5 v6 v6 v5 v7 v8 v9 v10 |
R1 R2 R1 R2 R1 R2 R1 R2 |
At the completion of this module, you will be able to


Notes:
Camera analogy:
Notes:
For most operations, you will not need to create your own matrix. You will simply tell OpenGL what operation to perform and OpenGL will create the appropriate matrix for you.
Notice how the subscripts on the matrix elements go down first and then across. If you're programming in C and you declare a matrix as m[4][4], then the element m[i][j] is in the ith column and jth row of the OpenGL transformation matrix. This is the reverse of the standard C convention in which m[i][j] is in row i and column j. To avoid confusion, you should declare your matrices as a one-dimensional array (m[16]).
Modeling Transformations are actions applied to the coordinate system. There are three types:
GLvoid glTranslatef( GLfloat Tx, GLfloat Ty,
GLfloat Tz )

Notes:
Alternate form:
GLvoid glTranslated( GLdouble x, GLdouble y,
GLdouble z )
GLvoid glRotatef( GLfloat angle, GLfloat x,
GLfloat y, GLfloat z )

Notes:
Alternate form:
GLvoid glRotated( GLdouble angle, GLdouble x,
GLdouble y, GLdouble z )
The angle parameter is different from the corresponding IRIS GL function. The angle parameter is specified in degrees, not tenths of degrees. Also note that this function is more general than the IRIS GL version in that we can rotate around any vector, not just the 'x', 'y', or 'z' axes.



GLvoid glScalef( GLfloat Sx, GLfloat Sy,
GLfloat Sz )

Notes:
| Scale Factor(s) | Effect |
| |s| > 1.0 | Expands dimension |
| |s| = 1.0 | Nothing |
| 0.0 < |s| < 1.0 | Shrinks dimension |
| s = 0.0 | BAD! Compresses dimension out of existence |
Note: the use of absolute values in the chart. The magnitude of the value determines whether the axis is stretched or reduced. If the value is negative, then the axis is also reflected 180 degrees.
Alternate form:
GLvoid glScaled( GLdouble x, GLdouble y, GLdouble z )
/* transforms.c - draw a triangle under the effect of a rotation,
* a translation and a scale
*
* Escape key - exit program
*/
#include <GL/glut.h> /* includes gl.h, glu.h */
#include <stdio.h>
/* Function Prototypes */
GLvoid initgfx( GLvoid );
GLvoid keyboard( GLubyte, GLint, GLint );
GLvoid drawScene( GLvoid );
void drawTriangle( GLfloat red, GLfloat green, GLfloat blue );
void printHelp( char * );
/* Global Definitions */
#define KEY_ESC 27 /* ascii value for the escape key */
void
main( int argc, char *argv[] )
{
GLsizei width, height;
glutInit( &argc, argv );
width = glutGet( GLUT_SCREEN_WIDTH );
height = glutGet( GLUT_SCREEN_HEIGHT );
glutInitWindowPosition( 0, height / 4 );
glutInitWindowSize( width / 2, height / 2 );
glutInitDisplayMode( GLUT_RGBA );
glutCreateWindow( argv[0] );
initgfx();
glutKeyboardFunc( keyboard );
glutDisplayFunc( drawScene );
printHelp( argv[0] );
glOrtho( -2.0, 2.0, -2.0, 2.0, -1.0, 1.0 );
glutMainLoop();
}
void
printHelp( char *progname )
{
fprintf(stdout, "\n%s - demonstrates modeling transformations\n\n"
"Escape Key - exit the program\n\n",
progname);
}
GLvoid
initgfx( GLvoid )
{
glClearColor( 0.0, 0.0, 1.0, 1.0 );
glShadeModel( GL_FLAT );
}
GLvoid
keyboard( GLubyte key, GLint x, GLint y )
{
switch (key) {
case KEY_ESC: /* Exit whenever the Escape key is pressed */
exit(0);
}
}
GLvoid
drawTriangle( GLfloat red, GLfloat green, GLfloat blue )
{
glColor3f( red, green, blue );
glBegin( GL_TRIANGLES );
glVertex2f( -0.5, -0.5 );
glVertex2f( 0.5, -0.5 );
glVertex2f( 0.0, 0.5 );
glEnd();
}
GLvoid
drawScene( GLvoid )
{
glClear( GL_COLOR_BUFFER_BIT );
/* draw a black triangle centered at the origin */
drawTriangle( 0.0, 0.0, 0.0 );
/* Draw x and y axes to show the origin */
XYaxes();
/* move over a bit and draw a dark gray triangle */
glTranslatef( 0.5, 0.0, 0.0 );
drawTriangle( 0.3, 0.3, 0.3 );
/* move over a bit and draw a rotated triangle */
glTranslatef( 0.5, 0.0, 0.0 );
/* Rotate 15 degrees clockwise around the positive Z axis */
glRotatef( -15.0, 0.0, 0.0, 1.0 );
drawTriangle( 0.7, 0.7, 0.7 ); /* draw light gray triangle */
/* move over a bit and draw a scaled triangle */
glTranslatef( 0.5, 0.0, 0.0 );
/* Scale the triangle by one-half in all dimensions, and
* reflect about the x axis
*/
glScalef( -0.5, 0.5, 0.5 );
drawTriangle( 1.0, 1.0, 1.0 ); /* draw white triangle */
XYaxes();
glFlush();
}
Notes:
This program demonstrates the three types of modeling transformations: rotation, scaling, and translation. It draws four triangles.
The first triangle is rendered at the origin. An x-y axis is also rendered, to help visualize the effects of subsequent transformations.
The second triangle is translated a short distance in the positive x direction.
The third triangle is translated a short distance in the positive x direction and then rotated slightly.
The last triangle is translated a short distance in the positive x direction, rotated slightly, and then scaled by one-half. It is also reflected about the new x axis. Another set of axes is rendered to show the reflection.
The XYaxes() function renders the x axis in red and the y axis in green. It helps to visualize the transformations and is useful to use when developing code. The XYaxes() function is available in the class library.

Notes:
You can use the right mouse button to bring up a menu which allows you to choose the type of modeling transformation.
Under Windows NT this tutorial occasionally does not display correctly until it has been iconized and restored.
Projection transformations define how much of the world you can see and how you view it. There are two types:

Notes:
We have already seen one type of projection transformation -- glOrtho().
GLvoid glOrtho( GLdouble left, GLdouble right,
GLdouble bottom, GLdouble top,
GLdouble nearClip, GLdouble farClip )

Notes:
Think of it is as though the viewing volume was flattened from the back to the front, and the result was placed on the screen.
Until now, all of our rendering has been done in only two dimensions (the z coordinate has been 0.0).

Try rotating the grid around the x axis (1.0, 0.0, 0.0) to make it three-dimensional.
/* orthoRotate.c - rotate the line grid around the X axis, making
* it an object in '3D'.
*
* Escape Key - exit program
*/
#include <GL/glut.h> /* includes gl.h, glu.h */
#include <stdio.h>
/* Function Prototypes */
GLvoid initgfx( GLvoid );
GLvoid keyboard( GLubyte, GLint, GLint );
GLvoid drawScene( GLvoid );
void printHelp( char * );
/* Global Definitions */
#define KEY_ESC 27 /* ascii value for the escape key */
void
main( int argc, char *argv[] )
{
GLsizei width, height;
glutInit( &argc, argv );
width = glutGet( GLUT_SCREEN_WIDTH );
height = glutGet( GLUT_SCREEN_HEIGHT );
glutInitWindowPosition( 0, height / 4 );
glutInitWindowSize( width / 2, height / 2 );
glutInitDisplayMode( GLUT_RGBA );
glutCreateWindow( argv[0] );
initgfx();
glutKeyboardFunc( keyboard );
glutDisplayFunc( drawScene );
printHelp( argv[0] );
glOrtho( -2.0, 2.0, -2.0, 2.0, -1.0, 1.0 );
glutMainLoop();
}
void
printHelp( char *progname )
{
fprintf(stdout,
"\n%s - render a rotated grid using an orthographic projection\n\n"
"Escape Key - exit the program\n\n",
progname);
}
GLvoid
initgfx( GLvoid )
{
glClearColor( 0.0, 0.0, 1.0, 1.0 );
glShadeModel( GL_FLAT );
}
GLvoid
keyboard( GLubyte key, GLint x, GLint y )
{
switch (key) {
case KEY_ESC: /* Exit when the Escape key is pressed */
exit(0);
}
}
GLvoid
drawScene( GLvoid )
{
static GLfloat whiteColor[] = { 1.0, 1.0, 1.0 };
glClear( GL_COLOR_BUFFER_BIT );
/* Rotate grid around the X axis - push the top of the grid
* into the screen
*/
glRotatef( -60.0, 1.0, 0.0, 0.0 );
glColor3fv( whiteColor );
WireGrid();
glFlush();
}
Notes:
This program draws a wire grid rotated 60 degrees around the x axis. The grid should look as though the top is pushed in and the bottom is sticking out, but it doesn't. Explain why not.
Note: The WireGrid function is a version of the grid we saw in grid.c. It is available in the class library.
The grid still looks like it was rendered with z = 0.0, and it looks as though it was scaled in the y dimension. Why?

Notes:
The reason the grid looks squashed in the y direction, rather than appearing 3D, has to do with the way the scene is projected onto the screen.
GLvoid glFrustum( GLdouble left, GLdouble right,
GLdouble bottom, GLdouble top,
GLdouble nearClip, GLdouble farClip )

Notes:
The eye is located at the origin and is looking down the negative z axis (into the screen). Near and far specify the distance from the eye (0.0 < near < far) of the near and far clipping planes along the negative z axis. The near clipping plane is specified by (left, bottom, -near) as the lower left corner and (right, top, -near) as the upper right corner. Changing near changes the shape of the viewing volume

glFrustum() is not intuitive to use, so a related function was added to the GLU library.
GLvoid gluPerspective( GLdouble fovy, GLdouble
aspect, GLdouble nearClip,
GLdouble farClip )

Notes:
gluPerspective creates a viewing frustum using glFrustum. You just provide the information in a different way. glFrustum provides more flexibility in that it allows you to specify a frustum that is not symmetric in x and y. This means that the line of sight does not have to be centered in the middle of the projection plane.
near and far are the same, but instead of specifying left, right, bottom, top, you give an angle for the field of view in y (fovy) and the aspect ratio. fovy determines the height, and the height combined with the aspect ratio determines the width
aspect determines the width of the frustum.
To see your objects, you need to make sure they are in the frustum.
gluPerspective( 45.0, 1.0, 3.0, 7.0 ); ... /* sometime before drawing scene */ glTranslatef( 0, 0, -5.0 );

Notes:
For now, we will just move our objects down the negative z axis. We'll see other ways to do this later.

Because the eye is initially at the origin of the system, and we tend to draw the objects there, they will not be in the viewing volume. We need to move the coordinate system between -near and -far
/* perspectiveRotate.c - rotate the line grid around the X axis,
* making it an object in '3D'. View it using a perspective projection.
*
* Escape Key - exit program
*/
#include <GL/glut.h> /* includes gl.h, glu.h */
#include <stdio.h>
/* Function Prototypes */
GLvoid initgfx( GLvoid );
GLvoid keyboard( GLubyte, GLint, GLint );
GLvoid drawScene( GLvoid );
void printHelp( char * );
/* Global Definitions */
#define KEY_ESC 27 /* ascii value for the escape key */
void
main( int argc, char *argv[] )
{
GLsizei width, height;
GLdouble aspect;
glutInit( &argc, argv );
width = glutGet( GLUT_SCREEN_WIDTH );
height = glutGet( GLUT_SCREEN_HEIGHT );
glutInitWindowPosition( (width / 2) + 2, height / 4 );
glutInitWindowSize( width / 2, height / 2 );
glutInitDisplayMode( GLUT_RGBA );
glutCreateWindow( argv[0] );
initgfx();
glutKeyboardFunc( keyboard );
glutDisplayFunc( drawScene );
printHelp( argv[0] );
gluPerspective( 45.0, (GLdouble) width/(GLdouble)height, 3.0, 7.0 );
/* Translate the origin so that it is between the near and far
* clipping planes.
*/
glTranslatef( 0.0, 0.0, -5.0 );
glutMainLoop();
}
void
printHelp( char *progname )
{
fprintf(stdout,
"\n%s - render a rotated grid using a perspective projection\n\n"
"Escape Key - exit the program\n\n",
progname);
}
GLvoid
initgfx( GLvoid )
{
glClearColor( 0.0, 0.0, 1.0, 1.0 );
glShadeModel( GL_FLAT );
}
GLvoid
keyboard( GLubyte key, GLint x, GLint y )
{
switch (key) {
case KEY_ESC: /* Exit when the Escape key is pressed */
exit(0);
}
}
GLvoid
drawScene( GLvoid )
{
static GLfloat whiteColor[] = { 1.0, 1.0, 1.0 };
glClear( GL_COLOR_BUFFER_BIT );
/* Rotate grid around the X axis - push the top of the grid
* into the screen
*/
glRotatef( -60.0, 1.0, 0.0, 0.0 );
/* Draw grid centered around translated origin */
glColor3fv( whiteColor );
WireGrid();
glFlush();
}
Notes:
This program is the same as orthoRotate.c, except that we are using a perspective projection instead of an orthographic projection.
The call to gluPerspective sets up the perspective projection. After setting up the projection transformation, the program does a translate so that all objects are inside the viewing volume.

Notes:
You can use the right mouse button to bring up a menu which allows you to choose the type of projection transformation.
Under Windows NT this tutorial occasionally does not display correctly until it has been iconized and restored.
There are two matrix stacks used to save projection and modeling transformations.

Notes:
Up to now we have not been using these two stacks. We've been accumulating all of the transformations on the ModelView matrix stack
Each vertex is first multiplied by the ModelView matrix, then by the Projection matrix.

GLvoid glMatrixMode( GLenum mode )
| mode | Where transformations happen |
| GL_PROJECTION GL_MODELVIEW |
Projection Matrix ModelView Matrix |
Most work is done on the ModelView matrix stack.
glMatrixMode( GL_PROJECTION ); gluPerspective( 45.0, 1.0, 3.0, 7.0 ); glMatrixMode( GL_MODELVIEW );
Notes:
The default matrix stack is GL_MODELVIEW.
Note: Because the matrix stack had not yet been introduced, the previous example programs didn't call glMatrixMode(GL_PROJECTION). Consequently, the projection transformations were specified on the ModelView stack. This is not a recommended practice.
GLvoid glPushMatrix( GLvoid ) GLvoid glPopMatrix( GLvoid )

Make sure that the number of pushes and pops match.
Notes:
Indenting code between Push/Pop pairs helps readability.
In GL_MODELVIEW mode, the matrix stack depth is at least 32. In GL_PROJECTION mode, the depth is at least 2. You can use the query command glGetIntegerv() to determine the maximum stack depth or the current stack pointer. See man glGet(3G) for explanations of GL_MODELVIEW_STACK_DEPTH, GL_MAX_MODELVIEW_STACK_DEPTH, GL_PROJECTION_STACK_DEPTH, and GL_MAX_PROJECTION_STACK_DEPTH.
GLvoid glLoadIdentity( GLvoid )
Replaces the current matrix (the top of the stack) with the identity matrix

Notes:
The glLoadIdentity() function is indispensable in working with the matrix stacks. Although it is not used in the following example program, its use will be discussed further in Lecture 6, Viewports.
Other matrix stack operations include:
| glLoadMatrix*() | Load a specified matrix onto the stack |
| glGetFloatv() | Return the matrix on the top of the specified matrix stack |
| glMultMatrix*() | Multiply the current matrix with a specified matrix |
The display function is called whenever the window is resized or exposed.

/* matrixmodes.c - draw a triangle under the effect of a rotation,
* a translation and a scale; use the matrix stack
* to ensure that the scene is properly redrawn.
*
* Escape Key - exit program
*/
#include <GL/glut.h> /* includes gl.h, glu.h */
#include <stdio.h>
/* Function Prototypes */
GLvoid initgfx( GLvoid );
GLvoid keyboard( GLubyte, GLint, GLint );
GLvoid drawScene( GLvoid );
void drawTriangle( GLfloat red, GLfloat green, GLfloat blue );
void printHelp( char * );
/* Global Definitions */
#define KEY_ESC 27 /* ascii value for the escape key */
void
main( int argc, char *argv[] )
{
GLsizei width, height;
glutInit( &argc, argv );
width = glutGet( GLUT_SCREEN_WIDTH );
height = glutGet( GLUT_SCREEN_HEIGHT );
glutInitWindowPosition( (width / 2) + 2, height / 4 );
glutInitWindowSize( width / 2, height / 2 );
glutInitDisplayMode( GLUT_RGBA );
glutCreateWindow( argv[0] );
initgfx();
glutKeyboardFunc( keyboard );
glutDisplayFunc( drawScene );
printHelp( argv[0] );
glMatrixMode( GL_PROJECTION );
gluPerspective( 45.0, (GLdouble) width/ (GLdouble)height, 3.0, 7.0 );
glMatrixMode( GL_MODELVIEW );
glutMainLoop();
}
void
printHelp( char *progname )
{
fprintf(stdout,
"\n%s - demonstrates use of matrix modes and stacks\n\n"
"Escape Key - exit the program\n\n",
progname);
}
GLvoid
initgfx( GLvoid )
{
glClearColor( 0.0, 0.0, 1.0, 1.0 );
glShadeModel( GL_FLAT );
}
GLvoid
keyboard( GLubyte key, GLint x, GLint y )
{
switch (key) {
case KEY_ESC: /* Exit whenever the Escape key is pressed */
exit(0);
}
}
GLvoid
drawTriangle( GLfloat red, GLfloat green, GLfloat blue )
{
glColor3f( red, green, blue );
glBegin( GL_TRIANGLES );
glVertex2f( -0.5, -0.5 );
glVertex2f( 0.5, -0.5 );
glVertex2f( 0.0, 0.5 );
glEnd();
}
GLvoid
drawScene( GLvoid )
{
glClear( GL_COLOR_BUFFER_BIT );
glPushMatrix();
/* Translate the origin so that it is between the near and far
* clipping planes.
*/
glTranslatef( 0.0, 0.0, -5.0 );
/* draw a black triangle centered at the origin */
drawTriangle( 0.0, 0.0, 0.0 );
/* Draw x and y axes to show the origin */
XYaxes();
/* move over a bit and draw another triangle */
glTranslatef( 0.5, 0.0, 0.0 );
drawTriangle( 0.3, 0.3, 0.3 );
/* move over a bit and draw a rotated triangle */
glTranslatef( 0.5, 0.0, 0.0 );
/* Rotate 15 degrees counter-clockwise around the positive Z axis */
glRotatef( -15.0, 0.0, 0.0, 1.0 );
drawTriangle( 0.7, 0.7, 0.7 );
/* move over a bit and draw a scaled triangle */
glTranslatef( 0.5, 0.0, 0.0 );
/* Scale the triangle by one-half in all dimensions */
glScalef( -0.5, 0.5, 0.5 );
drawTriangle( 1.0, 1.0, 1.0 ); /* draw green triangle */
XYaxes();
glPopMatrix();
glFlush();
}
Notes:
This program is the same as transforms.c, except that it has been modified to use the matrix stacks.
In main(), the program switches to the projection stack to set the projection transformation, and then returns to the ModelView stack.
In drawScene(), the program pushes a copy of the current ModelView matrix onto the ModelView stack, so that after rendering the scene the matrix can be restored. Because the matrix is restored each time the scene is drawn, the proportions of the objects within the scene remain constant when the window is resized. Compare this with the transforms example, in which the transformations accumulate with each rendering of the scene, causing the triangles to grow smaller and smaller.
void glRotatef( GLfloat angle, GLfloat x, GLfloat y, GLfloat z ) void glRotated( GLdouble angle, GLdouble x, GLdouble y, GLdouble z )
Computes a matrix that performs a counterclockwise rotation about the
specified vector from the origin through the point (x, y, z).
void glScalef( GLfloat scalex, GLfloat scaley, GLfloat scalez ) void glScaled( GLdouble scalex, GLdouble scaley, GLdouble scalez )
Scales the coordinate system along the x, y and z axes.
void glTranslatef( GLfloat transx, GLfloat transy, GLfloat transz ) void glTranslated( GLdouble transx, GLdouble transy, GLdouble transz )
Moves the coordinate system origin to the point specified by (x,y,z)
void glOrtho( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far )
Multiplies the current matrix by a matrix that describes a parallel
projection.
void gluOrtho2D( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top )
Multiplies the current matrix by a matrix that describes a
two-dimensional parallel projection. This is equivalent to calling glOrtho
with near=-1 and far=1.
void glFrustum( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far )
Multiplies the current matrix by a matrix that describes a perspective
projection.
void gluPerspective( GLdouble fovy, GLdouble aspect, GLdouble near, GLdouble far )
Multiplies the current matrix by a matrix that describes a perspective
projection, with a symmetrical, pyramid-shaped viewing volume.
void glMatrixMode( GLenum mode )
Specifies which matrix stack is the target for subsequent matrix
operations.
void glPushMatrix( GLvoid ) void glPopMatrix( GLvoid )
glPushMatrix() pushes the current matrix stack down by one,
duplicating the current matrix. glPopMatrix() pops the current
matrix stack, replacing the current matrix with the one below it on the
stack.
void glLoadIdentity( void );
Replaces the current matrix with the identity matrix.
void glLoadMatrixf( const GLfloat *m ) void glLoadMatrixd( const GLdouble *m )
Replaces the current matrix (as specified by the current matrix mode).
void glGetFloatv( GL_PROJECTION_MATRIX, GLfloat *m ) void glGetFloatv( GL_MODELVIEW_MATRIX, GLfloat *m )
Returns the matrix on the top of the specified matrix stack.
void glMultMatrixf( const GLfloat *m ) void glMultMatrixd( const GLdouble *m )
Multiplies the current matrix (as specified by the current matrix mode) with the one specified in m.
Using your knowledge about stack matrices and transformations, you have to:
chmod +x melite2bif you want a successful execution of the program.