600 likes | 732 Views
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)
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();