Chapter 2 - CG (2024)
Chapter 2 - CG (2024)
Faculty of Technology
Department of Computer Science
CoSc 3072 – Computer Graphics
Chapter 2 Handouts – Introduction to OpenGL
1. Introduction to OpenGL
OpenGL is based on the GL graphics package developed by the graphics hardware
manufacturer Silicon Graphics.
OpenGL( Open Graphics Library ) is cross-platform application programming interface
(API) for rendering 2D and 3D vector graphics. The API is typically used to interact with
a graphics processing unit (GPU), to achieve hardware-accelerated rendering. The
purpose of OpenGL is to send pieces of information from your computer’s central
processing unit to the graphics card device.
GL was a popular package but it was specific to Silicon Graphics systems, i.e. code
written using GL would only run on Silicon Graphics hardware. In an attempt to
overcome this limitation, OpenGL was developed in the early 1990’s as a free platform-
independent version of GL. The package was developed, and is still maintained, by a
consortium of graphics companies.
Although OpenGL is the core library that contains the majority of the functionality, there
are a number of associated libraries that are also useful. The following is a summary of
the most important of the OpenGL family of graphics libraries:
OpenGL: the core library, it is platform (i.e. hardware system) independent, but
not windows-system independent (i.e. the code for running on Microsoft
Windows will be different to the code for running on the UNIX environments X-
Windows or Gnome).
glut: The GL Utilities Toolkit, it contains some extra routines for drawing 3-D
objects and other primitives. Using glut with OpenGL enables us to write
windows-system independent code.
glu: The OpenGL Utilities, it contains some extra routines for projections and
rendering complex 3-D objects.
glui: Contains some extra routines for creating user-interfaces.
Features of OpenGL
The OpenGL library only contains rendering commands that are dependent of
operating system.
The OpenGL library is not capable of:
- Opening windows
- Responding to interrupts from mouse or keyboard.
- Operating system independent.
The Glut library provides the above these capabilities.
Every routine provided by OpenGL or one of the associated libraries listed above follows
the same basic rule of syntax:
The prefix of the function name is either gl, glu, or glut, depending on which of
these three libraries the routine is from.
The main part of the function name indicates the purpose of the function.
The suffix of the function name indicates the number and type of arguments
expected by the function. For example, the suffix 3f indicates that 3 floating point
arguments are expected.
For example, the function glVertex2i is an OpenGL routine that takes 2 integer arguments
and defines a vertex.
Some function arguments can be supplied as predefined symbolic constants. (These are
basically identifiers that have been defined using the C++ #define statement.) These
symbolic constants are always in capital letters, and have the same prefix convention as
function names. For example, GL_RGB, GL_POLYGON and GLUT_SINGLE are all
symbolic constants used by OpenGL and its associated libraries.
Finally, OpenGL has a number of built-in data types to help make it into a platform-
independent package. For example, the C++ int data type may be stored as a 16-bit
number on some platforms but as a 32-bit number on others.
Therefore if we use these standard C++ data types with OpenGL routines the resultant
code will not be platform-independent. OpenGL provides its own data types to overcome
this limitation. Mostly, they have the same names as C++ data types but with the prefix
GL attached. For example, GLshort, GLint, GLfloat and GLdouble are all built-in
OpenGL data types.
Although you will find that your OpenGL code will still work on your computer if you do
not use these data types, it will not be as portable to other platforms so it is recommended
that you do use them.
The first thing we need to know to be able to start writing OpenGL programs is which
header files to include. Exactly which header files are required depends upon which
library(s) are being used.
For example, if we are only using the core OpenGL library, then the following line must
be added near the beginning of your source code:
#include <GL/gl.h>
If we also want to use the GL Utilities library, we must add the following line:
#include <GL/glu.h>
#include <GL/glui.h>
If we want to use the glut library (and this makes using OpenGL a lot easier) we do not
need to include the OpenGL or glu header files.
#include <GL/glut.h>
This will automatically include the OpenGL and glu header files too.
Now we are ready to start writing OpenGL code. Refer to the code listing in Appendix A
for the following discussion. Before displaying any graphics primitives we always need
to perform some basic initialisation tasks, including creating a window for display. The
following lines initialise the glut library, define a frame buffer and create a window for
display.
glutInit(&argc, argv);
glutInitWindowSize(640,480);
glutInitWindowPosition(10,10);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutCreateWindow(“GLUT Points demo”);
glutInit(&argc, argv);
o This line initialises the glut library. We must call this function before any
others in our glut/OpenGL programs.
glutInitWindowSize(640,480);
o This function call sets the size of the display window in pixels.
glutInitWindowPosition(10,10);
o This line sets the position of the top-left corner of the display window,
measured in pixels from the top-left corner of the monitor screen.
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
o This line defines the type of frame buffer we want to have. Single RGB
(i.e. colour) frame buffer.
glutCreateWindow(“GLUT Points demo”);
o Finally, this function call creates the display window with the attributes
defined by the previous calls.
The most important event is the display event. This occurs whenever OpenGL decides
that it needs to redraw the display window. It is guaranteed to happen once at the
beginning of the event loop; after this it will occur whenever the window needs to be
redrawn, for example if it is hidden by another window and then uncovered. Any
primitives that we want to draw should be drawn in the display event callback function;
otherwise they will not be displayed.
glutDisplayFunc(myDisplay);
Now we are ready to start drawing graphics primitives. The first thing we need to
understand is that the OpenGL graphics package is a state system. This means that it
maintains a list of state variables, or state parameters, which will be used to define how
primitives will be drawn. These state variables are specified separately, before the
primitives are drawn. For example, if we want to draw a blue point on our display
window, we first set the drawing colour state variable to blue, and then we draw the point
at the specified location.
Therefore, before we actually draw any primitives, we need to set the values of some
state variables. The listing in Appendix A is for an OpenGL program that draws some
points on the display window, so before we draw the points we assign values for three
state variables (at the beginning of the myInit function):
In the first line we are defining the background colour to have an RGB value of (1,1,1),
which means white. When we clear the screen later on it will be cleared to white. The
fourth argument to glClearColor is the alpha value of the background colour. The alpha
value indicates the opacity of the colour (i.e. is it a semi-transparent colour?): a value of 1
means that it is completely opaque, or the transparency is zero. The second line listed
above defines the current drawing colour to be (0,0,0), or black. Any subsequently drawn
primitive will be drawn in this colour. The final line sets the point size to four pixels. Any
subsequent point primitives drawn will be drawn with this size.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 640.0, 0.0, 480.0);
These lines define how the 3-D points will be projected onto the 2-D image plane. We
will return to this important subject in later chapters, but for the moment we will give a
simplified version of what really happens. We start off with our graphics primitives
defined in world coordinates, then using 3-D to 2-D projection transformation we draw a
picture of how the primitives would appear if we took their picture using a virtual
camera. The final primitives, drawn in the display window, are in screen coordinates.
Therefore we must specify to OpenGL how it should map points in world coordinates to
points in screen coordinates. The three lines given above define this mapping. In effect,
we are saying that any primitive whose x coordinate lies between 0 and 640, and whose y
coordinate lies between 0 and 480, will be seen by the virtual camera and therefore drawn
in the display window.
For a full listing of the simple OpenGL program we have worked through in this section.
glClear: This function is used to clear the screen before drawing. The background
colour set earlier will be used for clearing.
glBegin, glVertex2i, glEnd: This sequence of commands draws a number of point
primitives. Actually the glBegin … glEnd pair of commands is used to draw many
different types of primitive in OpenGL, with the symbolic constant argument to
glBegin defining how the vertices in between should be interpreted.
#include <GL/glut.h>
void myInit(void)
{
glClearColor(1.0, 1.0, 1.0, 0.0); // white background
glColor3f(0,0,0); // black foreground
glPointSize(4.0); // size of points to be drawn
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT); // Clear Screen
glBegin(GL_POINTS); // draw 3 points
glVertex2i(100,50);
glVertex2i(100,130);
glVertex2i(150,130);
glEnd();
glFlush(); // send all output to the display
}