250 likes | 500 Views
Programming with OpenGL and GLUT. Glenn G. Chappell CHAPPELLG@member.ams.org 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
E N D
Programmingwith OpenGL and GLUT Glenn G. ChappellCHAPPELLG@member.ams.org 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? CS 381
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. CS 381
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! CS 381
Introduction to GLUT:What is GLUT? • GLUT = OpenGL Utility Toolkit • 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.” • Features • 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. CS 381
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. CS 381
Introduction to GLUT: Writing GLUT Programs • Start with an already written program. • Use the web or your own previous work. • Give credit where credit is due! • GLUT handles overall flow of control. • You write functions to … • 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. CS 381
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. CS 381
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. CS 381
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 andevery 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. CS 381
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. CS 381
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. CS 381
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. CS 381
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. CS 381
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. CS 381
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 of left side • x-coordinate of right side • y-coordinate of bottom • y-coordinate of top CS 381
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). CS 381
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? CS 381
intro2d.cpp:Function display [3/5] glBegin(GL_QUADS); glVertex2d(0.1, 0.1); glVertex2d(0.9, 0.1); glVertex2d(0.9, 0.9); glVertex2d(0.1, 0.9); glEnd(); • 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. CS 381
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). CS 381
intro2d.cpp:THE RULES • Rules for callbacks (display in particular): • 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. CS 381
STOPPED • We stopped here on Friday, September 12. • We will continue with the following slides on Monday. CS 381
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? CS 381
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. CS 381