600 likes | 747 Vues
This lecture explores the fundamentals of OpenGL's fixed-function pipeline as a state machine in graphics programming. Key concepts include the nature of graphics libraries, how OpenGL functions as an API to control hardware, and the dynamics of state variables during rendering. We also discuss practical programming strategies, including state management, handling color and line styles, and minimizing the impact of state changes on performance. This session is essential for any programmer looking to efficiently utilize graphics systems in their applications.
E N D
Lecture 02:OpenGL (Fixed-Function) COMP 175: Computer Graphics January 21, 2014
Admin Stuff • Assigned partner • If you would like to change partner… • Room switch • In-person grading/demo for the 5 assignments • (note: assignments are different from labs) • Schedule a time to demo your program • Use the submitted source code (via provide) • You are encouraged to continue to work on your project, but the new additions will be considered at a discount at the TA (or my) discretion
Graphics System/ GPU What is OpenGL? • Conceptual Graphics Framework • Graphics Library can be Direct3D, Java3D, OpenGL, etc. • It is a software API that controls the functions of a piece of hardware – the graphics card. • Can we run OpenGL programs remotely? (e.g., use linux.cs.tufts.edu remotely through SSH and X-tunneling?) Software Hardware Graphics Library Application program Application Model (database)
Graphics Library • In Immediate-Mode Fixed-Function mode, OpenGL acts as a state machine. • What is a state machine? • Every variable is a “global variable” • For example, the current color • You need to keep track of the states… Or query the graphics card if you forget • Which, of course, is slow
State Variables • Pseudo code: SetState (LineStyle, DASHED); SetState(LineColor, RED); DrawLine( PtStart = (x1,y1), PtEnd = (x2,y2) ); SetState (LineColor, BLUE); DrawLine( PtStart = (x2,y2), PtEnd = (x3,y3) ); SetState(LineStyle, SOLID); DrawLine( PtStart = (x3,y3), PtEnd = (x1,y1) ); What color and shape? What color and shape? What color and shape?
State Variables • Pseudo code: SetState (LineStyle, DASHED); SetState(LineColor, RED); DrawLine( PtStart = (x1,y1), PtEnd = (x2,y2) ); SetState (LineStyle, DASHED); SetState (LineColor, BLUE); DrawLine( PtStart = (x2,y2), PtEnd = (x3,y3) ); SetState(LineStyle, SOLID); SetState (LineColor, BLUE); DrawLine( PtStart = (x3,y3), PtEnd = (x1,y1) ); What color and shape? What color and shape? What color and shape?
State Variables – Pros and Cons • What if…? function DrawDashedTriangle (pt1,pt2,p3) { SetState( LineStyle, DASHED ); DrawLine( PtStart=pt1, PtStart=p2 ); DrawLine( PtStart=pt2, PtStart=p3 ); DrawLine( PtStart=pt3, PtStart=p1 ); } • What color is the triangle? • Pros:?? • Cons:??
State Variables – Pros and Cons • What if…? function DrawDashedTriangle (pt1,pt2,p3) { SetState( LineStyle, DASHED ); DrawLine( PtStart=pt1, PtStart=p2 ); DrawLine( PtStart=pt2, PtStart=p3 ); DrawLine( PtStart=pt3, PtStart=p1 ); } • What color is the triangle? • Pros: trickle down effect, caller can control the subroutine’s behavior • Cons: the color is undefined! Who set my color?!
State Variables – Pros and Cons • What’s right and what’s wrong with this? function DrawTriangle(pt1,pt2,p3, int origColor, int curColor, int origStyle, int curStyle ) { SetState( LineStyle, curStyle ); SetState(LineColor, curColor); DrawLine( PtStart=pt1, PtStart=p2 ); DrawLine( PtStart=pt2, PtStart=p3 ); DrawLine( PtStart=pt3, PtStart=p1 ); SetState( LineStyle, origStyle); SetState(LineColor, origColor); }
Still A Pain, but Cleaner… • Bundles and unsets… function DrawRedDashedTriangle(pt1,pt2,p3){ PushAttributeState(); SetState( LineStyle, DASHED ); SetState( LineColor, RED ); ... PopAttributeState(); } • This eliminates the state variable problem.
Another Example • What does this function do? //using idleFunc as the main render loop void idleFunc () { glTranslate3f (1, 0, 0); glBegin(GL_POINTS); glVertex3f (0, 0, 0); glEnd(); } • Where is the point showing up? • How do I get that value?
Forgetting the State? • What if I forget to set some state? DrawLine( PtStart = (x1,y1), PtEnd = (x2,y2) ); • What if I set the wrong state? SetState(LineStyle, 12345); DrawLine( PtStart=pt1, PtStart=p2 ); • What if I forget the state a variable is in?
Forgetting the State? • What if I forget to set some state? DrawLine( PtStart = (x1,y1), PtEnd = (x2,y2) ); • OpenGL provides some good default values. For example, for color, it’s set to (1,1,1,1) – non transparent white • How do I know if something worked? SetState(LineStyle, 12345); DrawLine( PtStart=pt1, PtStart=p2 ); • You don’t. Since it’s not clear if some configuration of states will send OpenGL spinning, if you suspect an error from OpenGL, call GlenumglGetError(void) • What if I forget the state a variable is in? • You should use this sparingly… But you can use void glGetBooleanv(Glenumparaname, Glboolean* params) void glGetFixedv(Glenumparaname, Glfixed* params) void glGetFloatv(Glenumparaname, Glfloat* params) void glGetIntegerv(Glenumparaname, Glint* params)
Programming Strategies? • What do you think is the best way to deal with the state machine and maintain state variables? • How to access local variables (that correspond to state variables)? • Efficiency considerations? • How do you think the programming with a state machine affects multi-threaded applications?
For Example • How many parameters do you have to pass to render an object? void render () { obj1->drawSelf(myMouse, myScreenSize, myTimer, ...); obj2->drawSelf(myMouse, myScreenSize, myTimer, ...); obj3->drawSelf(myMouse, myScreenSize, myTimer, ...); } • How do you enforce that there is only one instance of myMouse, myScreenSize, myTimer in code?
Possible Answers? • Use global variables • Use mutual references. For example: void setChild (CWidget* child) { myChild = child; child->setParent(this); } MyMouse* getMouse() { return myMouse; } void setParent (PWidget* parent) { myParent = parent; } voiddoStuff () { MyMouse mouse = myParent->getMouse(); doStuffWithMouse (mouse); }
Possible Answers? • Problems: • Need to guarantee a single instance of the states • Don’t want to pass a billion parameters during the execution of every child object • Don’t want the child to have to call parent->parent->parent->parent->getProperties(); • One possible answer is to use Singletons
Programming Strategies? • What do you think is the best way to deal with the state machine and maintain state variables? • How to access local variables (that correspond to state variables)? • Efficiency considerations? • How do you think the programming with a state machine affects multi-threaded applications?
Multi-Threading and OpenGL Thread A Thread B void drawRedDashedTriangle() { pushAttributes(); setColor (RED); setStyle (DASHED); drawLine (pt1+d, pt2+d); drawLine (pt2+d, pt3+d); drawLine (pt3+d, pt1+d); d++; popAttributes(); } void drawBlueSolidTriangle() { pushAttributes(); setColor (BLUE); setStyle (SOLID); drawLine (pt4-p, pt5-p); drawLine (pt5-p, pt6-p); drawLine (pt6-p, pt4-p); p--; popAttributes(); }
Multi-Threading and OpenGL Thread A Thread B void drawRedDashedTriangle() { mutex.lock(); pushAttributes(); setColor (RED); setStyle (DASHED); drawLine (pt1+d, pt2+d); drawLine (pt2+d, pt3+d); drawLine (pt3+d, pt1+d); d++; popAttributes(); mutex.unlock(); } void drawBlueSolidTriangle() { mutex.lock(); pushAttributes(); setColor (BLUE); setStyle (SOLID); drawLine (pt4-p, pt5-p); drawLine (pt5-p, pt6-p); drawLine (pt6-p, pt4-p); p--; popAttributes(); mutex.unlock(); }
Example • Here we use GLUT, which is a basic GL window implementation that is on all platforms. • Pros: cross-platform, command line, easy to use • Cons: no GUI support (no buttons, menus, etc.)
Example OpenGL Application int main( int argc, char** argv) { glutInit( &argc, argv ); // Boilerplate initialization glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); glutInitWindowPosition( 50, 50 ); //upper left glutInitWindowSize( 640, 480 ); // width, height, in pixels glutCreateWindow( "OpenGL Example" ); // window title glViewport( /* lower left corner of the viewport */ 0, 0, /* width, height of the viewport */ 640, 480 ); //lower left What’s going on here?
Example OpenGL Application int main( int argc, char** argv) { glutInit( &argc, argv ); // Boilerplate initialization glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); #define GLUT_RGB 0 #define GLUT_RGBA GLUT_RGB #define GLUT_INDEX 1 #define GLUT_SINGLE 0 #define GLUT_DOUBLE 2 #define GLUT_ACCUM 4 #define GLUT_ALPHA 8 #define GLUT_DEPTH 16 #define GLUT_STENCIL 32 #if {GLUT_API_VERSION >= 2} #define GLUT_MULTISAMPLE 128 #define GLUT_STEREO 256 #endif #if {GLUT_API_VERSION >= 3} #define GLUT_LUMINANCE 512 #endif
Example OpenGL Application int main( int argc, char** argv) { glutInit( &argc, argv ); // Boilerplate initialization glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ); glutInitWindowPosition( 50, 50 ); //upper left glutInitWindowSize( 640, 480 ); // width, height, in pixels glutCreateWindow( "OpenGL Example" ); // window title glViewport( /* lower left corner of the viewport */ 0, 0, /* width, height of the viewport */ 640, 480 ); //lower left Careful!!
Example OpenGL Application int main( int argc, char** argv) { glutInit( &argc, argv ); // Boilerplate initialization glutInitDisplayMode( GLUT_RGB | GLUT_DEPTH ); glutInitWindowPosition( 50, 50 ); //upper left glutInitWindowSize( 640, 480 ); // width, height, in pixels glutCreateWindow( "OpenGL Example" ); // window title glViewport( /* lower left corner of the viewport */ 0, 0, /* width, height of the viewport */ 640, 480 ); //lower left glShadeModel( GL_SMOOTH ); glPolygonMode( GL_FRONT, GL_FILL ); setupLighting(); setupCamera(640, 480); registerCallBacks(); glutMainLoop(); } Asks OpenGL to render with smooth (Gouraud) shading. Other option is GL_FLAT
Example OpenGL Application int main( int argc, char** argv) { glutInit( &argc, argv ); // Boilerplate initialization glutInitDisplayMode( GLUT_RGB | GLUT_DEPTH ); glutInitWindowPosition( 50, 50 ); //upper left glutInitWindowSize( 640, 480 ); // width, height, in pixels glutCreateWindow( "OpenGL Example" ); // window title glViewport( /* lower left corner of the viewport */ 0, 0, /* width, height of the viewport */ 640, 480 ); //lower left glShadeModel( GL_SMOOTH ); glPolygonMode( GL_FRONT, GL_FILL ); setupLighting(); setupCamera(640, 480); registerCallBacks(); glutMainLoop(); } Asks OpenGL to render fill the polygons but only in the front-facing side Options are GL_BACK, GL_FRONT_AND_BACK, and GL_POINT, GL_LINE, GL_FILL
Example OpenGL Application void setupLighting() { glEnable (GL_LIGHTING); glEnable (GL_LIGHT0); GLfloatwhiteColor[] = {0.25f, 0.25f, 0.25f, 1.0f}; glLightfv (GL_LIGHT0, GL_AMBIENT, whiteColor); //directional (diffuse) light GLfloatwhiteFull[] = {1.0f, 1.0f, 1.0f, 1.0f}; GLfloatlightPos[] = {-1.0f, 1.0f, 1.0f, 0.0f}; glLightfv(GL_LIGHT0, GL_DIFFUSE, whiteFull); glLightfv(GL_LIGHT0, GL_POSITION, lightPos); GLfloat grey[] = {0.1f, 0.1f, 0.1f, 1.0f}; glMaterialfv(GL_FRONT, GL_DIFFUSE, grey); //reflect 10% diffuse glMaterialfv(GL_FRONT, GL_AMBIENT, whiteFull);}//reflect full ambient int main( int argc, char** argv) { glutInit( &argc, argv ); // Boilerplate initialization glutInitDisplayMode( GLUT_RGB | GLUT_DEPTH ); glutInitWindowPosition( 50, 50 ); //upper left glutInitWindowSize( 640, 480 ); // width, height, in pixels glutCreateWindow( "OpenGL Example" ); // window title glViewport( /* lower left corner of the viewport */ 0, 0, /* width, height of the viewport */ 640, 480 ); //lower left glShadeModel( GL_SMOOTH ); glPolygonMode( GL_FRONT, GL_FILL ); setupLighting(); setupCamera(640, 480); registerCallBacks(); glutMainLoop(); }
Example OpenGL Application void setupCamera(int w, int h) { glMatrixMode (GL_PROJECTION); glLoadIdentity(); //left, right, bottom, top gluOrtho(-1, 1, -1, 1); //same as: (adds near, far) //glOrtho(-1,1,-1,1,-1,1); //or perspective transform //gluPerspective( // 45, //y-axis field of view // ((float)w/(float)h), // ratio of FOV(x) to FOV(y) // 0.02, //distance to near clip plane // 1000 //distance to far clip plane // ); glMatrixMode (GL_MODELVIEW); glLoadIdentity(); } int main( int argc, char** argv) { glutInit( &argc, argv ); // Boilerplate initialization glutInitDisplayMode( GLUT_RGB | GLUT_DEPTH ); glutInitWindowPosition( 50, 50 ); //upper left glutInitWindowSize( 640, 480 ); // width, height, in pixels glutCreateWindow( "OpenGL Example" ); // window title glViewport( /* lower left corner of the viewport */ 0, 0, /* width, height of the viewport */ 640, 480 ); //lower left glShadeModel( GL_SMOOTH ); glPolygonMode( GL_FRONT, GL_FILL ); setupLighting(); setupCamera(640, 480); registerCallBacks(); glutMainLoop(); }
Example OpenGL Application int main( int argc, char** argv) { glutInit( &argc, argv ); // Boilerplate initialization glutInitDisplayMode( GLUT_RGB | GLUT_DEPTH ); glutInitWindowPosition( 50, 50 ); //upper left glutInitWindowSize( 640, 480 ); // width, height, in pixels glutCreateWindow( "OpenGL Example" ); // window title glViewport( /* lower left corner of the viewport */ 0, 0, /* width, height of the viewport */ 640, 480 ); //lower left glShadeModel( GL_SMOOTH ); glPolygonMode( GL_FRONT, GL_FILL ); setupLighting(); setupCamera(640, 480); registerCallBacks(); glutMainLoop(); } void registerCallbacks() { glutReshapeFunc (myReshape); glutKeyboardFunc(myKeyboard); glutMouseFunc(myMouseClick); glutMotionFunc(myMouseMove); glutDisplayFunc (myDisplay); glutIdleFunc (myIdle); }
Example OpenGL Application void myReshape(GLint width, GLint height) { //called when the window is resized glViewport(0, 0, width, height); setupCamera(width, height); } void myKeyboard (unsigned car key, int x, int y) { //called on keyboard event switch (key) { case ‘a’: someGlobalVariable = 1; : : } } void registerCallbacks() { glutReshapeFunc (myReshape); glutKeyboardFunc(myKeyboard); glutMouseFunc(myMouseClick); glutMotionFunc(myMouseMove); glutDisplayFunc (myDisplay); glutIdleFunc (myIdle); }
Example OpenGL Application void myMouseClick(int button, int state, int x, int y) { //called when a mouse click occurs if (button == GLUT_LEFT_BUTTON) { if (state == GLUT_DOWN) { globalVariableMouseDown = true; } else { globalVariableMouseDown = false; } } } void myMouseMove (int x, int y) { //called when a mouse move occurs if (globalVariableMouseDown==true) { //dragging occurs } } void registerCallbacks() { glutReshapeFunc (myReshape); glutKeyboardFunc(myKeyboard); glutMouseFunc(myMouseClick); glutMotionFunc(myMouseMove); glutDisplayFunc (myDisplay); glutIdleFunc (myIdle); }
Example OpenGL Application void display(void) { //called when the window needs to paint itself glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); drawMyStuff(); glutSwapBuffers(); numberOfFrames++; } void myIdle (void) { //called ALL THE TIME!! DWORD time_now= GetTickCount(); float diff = (float)(time_now-last_check_time)/1000.0; if (diff > 1.0) { float frameRate = numberOfFrames / (float)diff; numberOfFrames = 0; last_check_time = time_now; } glutPostRedisplay(); } void registerCallbacks() { glutReshapeFunc (myReshape); glutKeyboardFunc(myKeyboard); glutMouseFunc(myMouseClick); glutMotionFunc(myMouseMove); glutDisplayFunc (myDisplay); glutIdleFunc (myIdle); }
Example OpenGL Application int main( int argc, char** argv) { glutInit( &argc, argv ); // Boilerplate initialization glutInitDisplayMode( GLUT_RGB | GLUT_DEPTH ); glutInitWindowPosition( 50, 50 ); //upper left glutInitWindowSize( 640, 480 ); // width, height, in pixels glutCreateWindow( "OpenGL Example" ); // window title glViewport( /* lower left corner of the viewport */ 0, 0, /* width, height of the viewport */ 640, 480 ); //lower left glShadeModel( GL_SMOOTH ); glPolygonMode( GL_FRONT, GL_FILL ); setupLighting(); setupCamera(640, 480); registerCallBacks(); glutMainLoop(); } No turning back at this point, we enter the infinite loop!
Drawing Primitives void drawMyStuff(void) { glBegin (...); //glColor3f(1.0f, 1.0f, 1.0f); //glNormal3f(0.0f, 0.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f); glVertex3f(1.0f, 2.0f, 1.0f); : : glEnd(); }
OpenGL Primitives • GL_POINTSGL_LINESGL_LINE_STRIPGL_LINE_LOOPGL_TRIANGLESGL_TRIANGLE_STRIPGL_TRIANGLE_FANGL_QUADSGL_QUAD_STRIPGL_POLYGON
OpenGL Primitives • GL_POINTSGL_LINESGL_LINE_STRIPGL_LINE_LOOPGL_TRIANGLESGL_TRIANGLE_STRIPGL_TRIANGLE_FANGL_QUADSGL_QUAD_STRIPGL_POLYGON
OpenGL Primitives • GL_POINTSGL_LINESGL_LINE_STRIPGL_LINE_LOOPGL_TRIANGLESGL_TRIANGLE_STRIPGL_TRIANGLE_FANGL_QUADSGL_QUAD_STRIPGL_POLYGON
OpenGL Primitives • GL_POINTSGL_LINESGL_LINE_STRIPGL_LINE_LOOPGL_TRIANGLESGL_TRIANGLE_STRIPGL_TRIANGLE_FANGL_QUADSGL_QUAD_STRIPGL_POLYGON
Ordering of Vertices • void glFrontFace (GLenummode) • mode can be either GL_CW or GL_CCW • GL_CCW is the default
OpenGL Primitives • GL_POINTSGL_LINESGL_LINE_STRIPGL_LINE_LOOPGL_TRIANGLESGL_TRIANGLE_STRIPGL_TRIANGLE_FANGL_QUADSGL_QUAD_STRIPGL_POLYGON
OpenGL Primitives • GL_POINTSGL_LINESGL_LINE_STRIPGL_LINE_LOOPGL_TRIANGLESGL_TRIANGLE_STRIPGL_TRIANGLE_FANGL_QUADSGL_QUAD_STRIPGL_POLYGON
OpenGL Primitives • GL_POINTSGL_LINESGL_LINE_STRIPGL_LINE_LOOPGL_TRIANGLESGL_TRIANGLE_STRIPGL_TRIANGLE_FANGL_QUADSGL_QUAD_STRIPGL_POLYGON
OpenGL Primitives • GL_POINTSGL_LINESGL_LINE_STRIPGL_LINE_LOOPGL_TRIANGLESGL_TRIANGLE_STRIPGL_TRIANGLE_FANGL_QUADSGL_QUAD_STRIPGL_POLYGON
OpenGL Primitives • GL_POINTSGL_LINESGL_LINE_STRIPGL_LINE_LOOPGL_TRIANGLESGL_TRIANGLE_STRIPGL_TRIANGLE_FANGL_QUADSGL_QUAD_STRIPGL_POLYGON 1. Must be convex 2. Cannot intersect
Color Blending glColor3f (1.0, 0.0f, 0.0f); glBegin(GL_TRIANGLES); glVertex3f(-1.0f, -0.5f, -4.0f); // A glVertex3f( 1.0f, -0.5f, -4.0f); // B glVertex3f( 0.0f, 0.5f, -4.0f); // C glEnd();