Programming with OpenGL and GLUT Glenn G. Chappell

Download Report

Transcript Programming with OpenGL and GLUT Glenn G. Chappell

Programming
with OpenGL and GLUT
Glenn G. Chappell
[email protected]
U. of Alaska Fairbanks
CS 381 Lecture Notes
Friday, September 12, 2003
Review:
The Design of OpenGL

Recall:

The overall API design.
• What ideas guided the design of the API?

Naming conventions
• How are names of functions, constants,
and types are put together?

Types
• OpenGL defines its own simple types.
• Why?
• What type-related pitfalls should you watch out
for?
12 Sep 2003
CS 381
2
Review:
The Design of OpenGL

Attributes & Primitives


OpenGL functions as a state machine.
There are three kinds of functions:
• Those that set state.
• Those that return state.
• Those that draw.


Drawing is done via primitives.
States are used to set attributes of those
primitives.
12 Sep 2003
CS 381
3
Review:
OpenGL Primitives

The ten glBegin-style OpenGL Primitives

Points (1 primitive)
• GL_POINTS

Polylines (3 primitives)
• GL_LINES
• GL_LINE_STRIP
• GL_LINE_LOOP

Filled Polygons (6 primitives)
• Triangles
• GL_TRIANGLES
• GL_TRIANGLE_STRIP
• GL_TRIANGLE_FAN
• Quadrilaterals
• GL_QUADS
• GL_QUAD_STRIP
• General Polygons
• GL_POLYGON

Know the ten primitives! Know the associated vertex orderings!
12 Sep 2003
CS 381
4
Introduction to GLUT:
What is GLUT?

GLUT = OpenGL Utility Toolkit




Features





Not part of OpenGL.
By Mark J. Kilgard, formerly of SGI, currently at NVIDIA.
“GLUT is designed for constructing small to medium sized OpenGL
programs.”
Simplifies some OpenGL operations.
OS-independent interface for windows, pop-up menus, mouse,
keyboard, text fonts.
Optional flow-of-control handling for event-driven programming.
Utility functions for drawing shapes: sphere, cube, torus, etc.
C/C++ Header: <GL/glut.h>.

This includes gl.h and glu.h for you, as well as windows.h if it is
needed.
• Note: The handling of windows.h is sometimes incorrect under Cygwin.
You might need to #include it yourself if you use Cygwin.
12 Sep 2003
CS 381
5
Introduction to GLUT:
Thoughts on GLUT


I do not consider GLUT to be suitable for developing
professional-quality, production code.
We use it because:




It allows for OS-independent GUI programming.
It allows for short, easy-to-write programs that use graphics
in interesting ways.
It provides a relatively painless introduction to event-driven
programming.
So, as we cover event-driven programming:


Do not think, “Future employers will be happy that I know
GLUT.”
Instead, consider what general ideas about event-driven
programming are illustrated by the specific commands and
techniques we cover.
12 Sep 2003
CS 381
6
Introduction to GLUT:
Writing GLUT Programs

Start with an already written program.




GLUT handles overall flow of control.
You write functions to …





Use the web or your own previous work.
Give credit where credit is due!
Initialize OpenGL states and your own variables.
Draw things.
Handle events (mouse clicks, window changes,
keypresses, etc.).
Do something when nothing else happens.
These functions are called by GLUT, not you.
12 Sep 2003
CS 381
7
Introduction to GLUT:
An Example GLUT Program

We will now look at intro2d.cpp, a
simple OpenGL/GLUT program.

This program does 2-D graphics.
• 3-D CG is a bit trickier; I suggest (but do
not require) that you stick with 2-D for
assignment 2.

Source code is on the web page.
• You can use it to base your own programs
on, if proper credit is given.
12 Sep 2003
CS 381
8
intro2d.cpp:
Overview

5 functions: main, display, idle, keyboard, init

Function main
• Does initialization & window creation.
• Tells GLUT about display, idle, keyboard functions.
• Turns control over to GLUT.

Function init
• Called by main to initialize GL states, print instructions.

Function display
• Called by GLUT when something needs to be drawn.
• Updates the contents of the window.

Function idle
• Called by GLUT when nothing else is happening.
• In this program, the idle function only does error checking.

Function keyboard
• Called by GLUT when a key is pressed.
• Only handles ASCII keypresses. Use a GLUT “special” function for
other keys.
12 Sep 2003
CS 381
9
intro2d.cpp:
Beginning
//
//
//
//
//
//

intro2d.cpp
by Glenn G. Chappell
September 2003
For CS 381
Introductory 2-D OpenGL/GLUT program
Put comments like this on all programs for this class and
every other program you write for the rest of your life.
#include <GL/glut.h> // GLUT stuff,
includes OpenGL headers as well


Put this line at the beginning of all GLUT programs.
Again, the OpenGL headers are included by glut.h.
12 Sep 2003
CS 381
10
intro2d.cpp:
Function main [1/4]
int main(int argc, char ** argv)
{
// Initialize OpenGL/GLUT
glutInit(&argc, argv);

Above is always the same (argc, argv come from Unix command-line).
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

Main GLUT display configuration call




One parameter: multiple options bitwise-or’ed together.
GLUT_SINGLE means 1 color buffer (stores the color of a pixel).
GLUT_RGB means store actual color (no color look-up table [LUT]).
OpenGL Buffers



All looks like the viewport (portion of window where drawing occurs) in terms
of size, but hold different kinds of data.
Color buffers hold color. Essentially, color buffer = frame buffer.
Can allocate other buffers, e.g., GLUT_DEPTH for a depth buffer.
12 Sep 2003
CS 381
11
intro2d.cpp:
Function main [2/4]
// Make a window
glutInitWindowSize(startwinsize, startwinsize);
glutInitWindowPosition(50, 50);
glutCreateWindow("CS 381 - Introductory 2-D Program");

Specify window size (x,y), position (x,y), and title.


OS may ignore these and put window wherever it feels like.
Function glutCreateWindow also creates an “OpenGL context”.



An OpenGL context is a copy of all the OpenGL states related to a
particular output channel (generally a window).
So, don’t set any OpenGL states until after doing glutCreateWindow.
You can have multiple contexts. Changing a state (e.g., drawing
color) in one context does not affect the others.
12 Sep 2003
CS 381
12
intro2d.cpp:
Function main [3/4]
// Initialize GL states & register callbacks
init();
glutDisplayFunc(display);
glutIdleFunc(idle);
glutKeyboardFunc(keyboard);

Tell GLUT what function to call to draw window contents (display), what
to call when nothing is happening (idle), and what to call when an ASCII
keypress happens (keyboard).
display, idle, keyboard are callbacks; need to be registered with GLUT.

Other callbacks can be registered using functions like


glutMouseFunc (for mouse events)
glutReshapeFunc (for when the user resizes the window)

and others …


These functions only register the callbacks; they do not call them.
12 Sep 2003
CS 381
13
intro2d.cpp:
Function main [4/4]
// Do something
glutMainLoop();
return 0;
}




Very little has actually happened so far; we have merely done
initialization.
But now we turn control over to GLUT, callbacks get called, and
the program really starts running.
GLUT handles high-level flow of control from now on; when
something needs to be done, GLUT calls the appropriate
callback.
“return 0;” is just to keep the compiler happy. Since
glutMainLoop never returns, this line is never executed.
12 Sep 2003
CS 381
14
intro2d.cpp:
Function init [1/2]
void init()
{
glClearColor(1.0, 1.0, 1.0, 0.0);


Here we set various GL states.
The first state to set is the clear color.



This is the color to set all pixels to when the viewport is
cleared. Think of it as the background color.
Set to white: 100% red, 100% green, 100% blue.
4th parameter is alpha.


Alpha is used for many things; most common use is
transparency.
Alpha not used in this program, but it is a required
parameter.
12 Sep 2003
CS 381
15
intro2d.cpp:
Function init [2/2]
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 1.0, 0.0, 1.0);
glMatrixMode(GL_MODELVIEW); // Always go back to
model/view mode



In OpenGL, drawing data is sent through a pipeline, in which
transformations are applied to vertex coordinates. These
transformations are stored as 4×4 matrices.
Here, we set up the matrix to do the projection onto the screen.
What is important to know now is that the 4 parameters of
gluOrtho2D set up a coordinate system for the window:




x-coordinate
x-coordinate
y-coordinate
y-coordinate
12 Sep 2003
of
of
of
of
left side
right side
bottom
top
CS 381
16
intro2d.cpp:
Function display [1/5]
void display()
{
glClear(GL_COLOR_BUFFER_BIT);



The first thing to do when displaying is to clear the buffer.
glClear sets every pixel in the color buffer to the color specified
with glClearColor.
Can clear other buffers (if they were allocated by the
glutInitDisplayMode call).
12 Sep 2003
CS 381
17
intro2d.cpp:
Function display [2/5]
glColor3d(0.9, 0.1, 0.1);

Sets the drawing color.



This is the color of upcoming vertices.
Drawing color is another GL state.
glColor can take several forms with different types of
parameters.

What does “3d” mean?
12 Sep 2003
CS 381
18
intro2d.cpp:
Function display [3/5]
glBegin(GL_QUADS);
glVertex2d(0.1,
glVertex2d(0.9,
glVertex2d(0.9,
glVertex2d(0.1,
glEnd();

0.1);
0.1);
0.9);
0.9);
Specifying the coordinates of actual things to draw is done between
glBegin and glEnd.




glVertex call gives coordinates; GL_QUADS tells how to use them.
Coordinate system was specified by the glOrtho2D call.
Recall: GL_QUADS is a GL primitive; it means draw a series of quadrilaterals.
Indentation between glBegin and glEnd is helpful.
• It is not required, of course.

Only a very limited set of GL commands are allowed between glBegin and
glEnd.
12 Sep 2003
CS 381
19
intro2d.cpp:
Function display [4/5]
glFlush();
}



glFlush says “start drawing now”.
Another possibility is glFinish: start and wait until done.
In this class, always flush at the end your display function. Use
glFlush, glFinish, or glutSwapBuffers (to be discussed later).
12 Sep 2003
CS 381
20
intro2d.cpp:
THE RULES
Rules for callbacks (display in particular):

1.
2.
3.
You never call your callback functions. Only GLUT
does that.
The display function only does drawing (which may
include GL state changes).
No drawing is done outside the display function (but
state changes may be done).
These rules are for this class.



Later in life, you may want to break them.
But think hard first; they’re good rules.
12 Sep 2003
CS 381
21
STOPPED
We stopped here on Friday,
September 12.
 We will continue with the following
slides on Monday.

12 Sep 2003
CS 381
22
intro2d.cpp:
Function keyboard
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case ESCKEY: // ESC: Quit
exit(0);
break;
}
}

GLUT calls the keyboard function whenever an ASCII keypress happens.




Use the GLUT “special” function for non-ASCII (like arrow keys).
The ASCII value of the keypress is in key. Mouse position is in x, y.
Your keyboard (or special) function will usually be one big switch.
Why did I put in the (unnecessary) break?
12 Sep 2003
CS 381
23
intro2d.cpp:
Function idle
// Print OpenGL errors, if there are any
(for debugging)
if (GLenum err = glGetError())
{
cerr << "OpenGL ERROR: " << gluErrorString(err)
<< endl;
}

GLUT calls the idle function whenever nothing else needs doing.


It is useful for making time-dependent changes to the scene.
Here, we check for OpenGL errors, and print a message if there
is an error.

This is a rather atypical use of the idle function.
12 Sep 2003
CS 381
24