Escolar Documentos
Profissional Documentos
Cultura Documentos
TwoclassesofprojectionaresupportedbyOpenGL Perspectiveprojection
Theprojectionisdefinedby:
anditscharacteristicsinclude:
IntheOpenGLimplementationtheviewplaneandnearclippingplanescoincideandsovisibleimage isactuallyprojecteduponthenearclippingplane. 1
Orthographicprojection Orthographicprojectionisaspecialcaseofparallelprojection.
Theprojectionisdefinedby:
anditscharacteristicsinclude:
Thustheviewvolumeisacubecenteredattheoriginandhavingedgesoflength2anditseight verticesarelocatedat(x=+/1.0,y=+/1.0,z=+/1.0).
Projection
Theprojectionofthepoint(x,y,z)thatsurvivesclippingissimply(x,y,0);
DisplayingimagesinOpenGL Sinceimagesare2Dimensionalobjects,parallelprojectionisanaturalapproachforprojectingthem. InOpenGLthedefaultDOPis(0,0,1)andthedefaultviewvolumeis(+/1.0,+/1.0,+/1.0). TheglOrtho()functioncanbeusedto scaleandtranslatethedefaultviewvolumetooneofadifferentsizeandlocationbut theDOPandcannotbechangedbyglOrtho.(Itcanbechangedbyapplyingarotationtothe Projectionmatrix). Thenearclippingplanehasverticesat(x,y,nearVal)andthefarclippingplane(x,y,farVal). Sotocreateacanonicalviewvolume,use1fornearValand1forfarVal!Invertingthesignshasno effectbutmakingthemsamewillmaketheviewvolumeEMPTY. void glOrtho( GLdouble GLdouble GLdouble GLdouble GLdouble GLdouble
tx
2 --------top - bottom
ty
-2 ---------far - near 0 0
tz
0 Where
tx = -(right + left) ------------right - left
ty =
/**/ int gg_image_window( image_t *img) { int winid; int i; int found = 0; /* This won't work here */ #if 0 glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glClearColor(0.3, 0.0, 0.0, 1.0); #endif
Creatingaviewingwindow OneofthemorechallengingaspectsofOpenGLprogrammingismentallytrackingtheactivestateand understandingconstraintsonwhenandinwhatorderthestatevariablesmustbechanged.For example, glutInitWindowSize()mustbecalledbeforeglutCreateWindow(). HereitappearstheglViewport()doesnothingatall. Discoveringthissortofthingoftentakesalotoftrialanderror. glutInitWindowSize(img->width, img->height); winid = glutCreateWindow(img->filename); /* Not needed but doesn't do anything */ glViewport(0.0, 0.0, img->width/2, img->height/2);
Definingtheprojectionmatrix OneofOpenGLsstatevariablesisthecurrently"active"matrix:GL_PROJECTIONor GL_MODELVIEW.Theglufunctionsarewrappersforglfunctions.Thetwoapproachesshown below,bothaccomodateanimagerenderedinthez=0planeandwillnotclipobjectshavingzcoords in(1.1). /* Default projection doesn't work... image appears */ /* in upper right quadrant of window */ /* This creates a front clipping plane of -1 and */ /* a rear clipping plane of 1 */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); // gluOrtho2D(0.0, img->width, 0.0, img->height); glOrtho(0.0, img->width, 0.0, img->height, -1.0, 1.0);
10
Defininingadditionalstatevariables MostelementsofOpenGLaredisabledbydefault.Theycanbeselectivelyenabledanddisablevia glEnable()andglDisable(). IfGL_DEPTH_TESTisenabledthenthezcoordinateofeachpixelthatisrenderedisrememberedina DEPTH_BUFFER.Ifanotherpixelislaterrenderedtothesamelocation,itwillbevisibleifandonly ifitszcoordinateisgreaterthanthepixelthatalreadyresidesthere. Whendepthtestingisenableditisnecessarytoremembertoclearthedepthbufferasshownbelow everytimetheimageistoberedrawn. /* Elements of the GL state apply on a per window basis */ /* and must be set AFTER the window is created */ glEnable(GL_DEPTH_TEST); glClearColor(0.3, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
11
Blending OpenGLsupportscompositingofthetypewehavedone"manually."Itisusuallycalledalpha blending.Manyblendingfunctionsareavailable.Thisistheonewehavebeenusing.Whenanew pixelistobewrittentotheframebufferitsRGBcomponentsareweightedbythealphavalue associatedwiththenewpixel.Theexistingpixelisweighedby(1alpha). glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); Manyotherfunctionsaresupported.Mostarenotobviouslyuseful.Itispossible,forexample,touse thevalueoftheredchannelasablendingweight.Thiscanproducewierdandwonderouseffects. ThetwoparameterspassedtoglBlendFunc()arecalledsfactoranddfactor.Thesourcepixelis multipliedbythesfactorandtheexistingdestinationpixelbythedfactorandtheproductsareadded together. Asshownbelow,thefactorsmayeitherbescalars(e.g.,GL_SRC_ALPHA)orRGBtriples(e.g. GL_DST_COLOR). Ninesymbolicconstantsareaccepted:GL_ZERO,GL_ONE, GL_DST_COLOR,GL_ONE_MINUS_DST_COLOR,GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA,andGL_SRC_ALPHA_SATURATE. ThedefaultvalueisGL_ONE.
12
Wewrite: glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glScalef(0.5. 0.5, 1.0) glRotatef(30.0, 0.0, 0.0, 1.0); glTranslatef(-30.0, -20.0, 0.0); Thiswillproduceexactlythetransformweseek: M=IxScxRxT
13
TranslationinOpenGL Inthefollowingdiscussionwewillassumethatthecurrentmatrixisthemodelviewmatrixanditis calledM. void glTranslatef( GLfloat tx, GLfloat ty, GLfloat tz); Thisproducesthematrix,T= 1 0 0 0 0 1 0 0 0 0 1 0 tx ty tz 1
andcomputesanewmodelviewmatrixM=MT
14
ScalinginOpenGL void glScalef( GLfloat sx, GLfloat sy, GLfloat sz); Thisproducesthematrix,Sc= sx 0 0 0 0 sy 0 0 0 0 sz 0 0 0 0 1
andcomputesanewmodelviewmatrixM=MSc
15
RotationinOpenGL Rotationissomewhatmorecomplex.Thefirstparameterisananglespecifyingthemagnitudeofthe rotationindegrees.Thefollowingthreeparametersdefineavectoraboutwhichtherotationisto occur. Forexampleifwewishtorotatea2Dimagewhichlivesonthez=0planeaboutthezaxis(0,0,1). Thenxandycoordinatesofpixelvalueswillchangebutthezcoordinatewillnot. void glRotatef( GLfloat theta, GLfloat vx, GLfloat vy, GLfloat vz); Thefunctioncallgl_Rotatef(x,0.0,0.0,1.0)isproducesthematrix,R= cos(x) sin(x) -sin(x) cos(x) 0 0 0 0 0 0 1 0 0 0 0 1
andcomputesanewmodelviewmatrixM=MR
Rotationsaroundtheothercoordinateaxesarestraightforwardtocompute. Rotationsaroundgeneralvectorsarenotquitesostraightforward.
16
ShearinginOpenGL Oddly,thereisnoglShearf()function.However,thisexamplefoundonthewebdemonstrateshowto buildonthatshearsinxandy(butnotz)anduseglMultMatrixf()toapplyittothecurrentmartrix // Compute the Shear Matrix // OpenGL does not provide a Shear matrix // (that I could find yet) // Plus it illustrates how to pass ANYWAY // Matrix to OpenGL // Note: m goes down COLUMNS first... // m1, m2, m3, m4 represent m11, m21, m31, m41 // m5, m6, m7, m8 represent m12, m22, m32, m42 // etc... void shearMatrix(int shearX, int shearY) { float m[] = { 1, shearY, 0, 0, shearX, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 }; glMultMatrixf(m); } NOTE:OpenGLisshowingitsuglyFortranheritagehere!Theactualmatrixinnormal mathematicalandCnotationis,ofcourse: 1 shy 0 0 shx 1 0 0 0 0 1 0 0 0 0 1
WecanthususeglMultMatrix()toperformanyaffineorperspectivewarpinOpenGL. Thevalueofshxwillbedx/dyasbefore.
17
Example Supposewewishtoanimateacubewhichisspinningononeofitscorners.Thecallto glCallList(CUBE_LIST)rendersthecubewhosecenterisattheorigin,whoseedgesare2unitslong andwhoseverticesare(+/1,+/1,+/1) Foreachframeshownthevalueofrotatewillbeupdated. glRotatef(rotate, 0.0, 1.0, 0.0); glRotatef(-35.26434, 1.0, 0.0, 0.0); glRotatef(45.0, 0.0, 0.0, 1.0); glTranslatef(0.5, 0.5, 0.5); glScalef(0.5, 0.5, 0.5); glCallList(CUBE_LIST); /* /* /* /* /* /* Rotate around y axis Tip it up on point Roll it around z Move base to origin Shrink it Render centered cube */ */ */ */ */ */
Becauseofthewayinwhichthetransformsupdatethemodelviewmatrixthissequenceofcalls producesRot(rotate,y)Rot(35.2,x)Rot(45,z)T(0.5,0.5,0.5)Sc(0.5,0.5,0.5)(x,y,z,1)
18
19
Limitations Wemightwishtoaddacaptiontotheimageaswepreviouslydidusingthemanualapproach,butuse glScalef()toshrinkitandglRotatef()torotateit. void gg_add_image( image_t *new) { image_t *img = gg_find_image(); new->scale = 0.5; glRotatef(30.0, 0.0, 0.0, 1.0); glScalef(new->scale, new->scale, 1.0); glRasterPos2i(new->rx, new->ry); glDrawPixels(new->width, new->height, GL_RGBA, GL_FLOAT, new->fapixels); }
Weconcludefromthepicturethatmodelviewtransformationisappliedonlytothelowerleftcoordinate ofthepixmapandnottheindividualpixels.
20
Imagesastextures TobeabletousetofullpowerofOpenGLtotransformimageswecannotuseglDrawPixels(). WemustusetexturemappingtobindtheimagetoatwoDquadwhichcanbetransformedbythe modelviewmatrix. TheOpenGLtexturingsystemconsistsofatwolevelhierarchyofentities textureunits NamesareGL_TEXTURE0,GL_TEXTURE1,...etc ThedefaultunitisGL_TEXTURE0 Eachcontainsindependenttexturestates Onlyoneunitisactiveatatime.Itisactivatedby: glActiveTexture(GL_TEXTUREn); texture Namesare1,2,....etc.Texturename0isreservedandshouldnotbeused. Eachtexturealsocontainsstateinformation Auniquetexturenamecanbegeneratedandstoredinimg>tex_idvia: glGenTextures(1,&img>tex_id); Thefirstparameterindicateshowmanytextureid'saredesiredandthesecondistheaddressof anarraywheretheyaretobestored.Hereimg>tex_idisasingleunsignedint. Atexturecanbeboundtotheactivetextureunitby: glBindTexture(texture_type,texname); Inourexampleswewillusethedefaulttextureunitandrebindasneeded.Anotherapproachwouldbe tousetwounitsandswitchactivetextureswithoutrebinding. Thevalueoftexture_typewillbeGL_TEXTURE_2D.
21
Thetexturebaseddisplayroutine Hereweassumethat:
/**/ void tex_display() { image_t *img; img = gg_find_image(); glClear(GL_COLOR_BUFFER_BIT); gg_render_quad(img); if (foreground) { gg_render_fg(img,foreground,400.0, 200.0, -282.1, 0.18, 0.18); gg_render_fg(img,foreground,350.0, 150.0, -212.1, 0.24, 0.24); gg_render_fg(img,foreground,300.0, 100.0, -141.1, 0.3, 0.3); } glutSwapBuffers(); }
22
23
Creatinganewtexture void gg_make_texture( image_t *img, int apply) /* GL_MODULATE or GL_DECAL */ { /* Generate a unique "name" for the texture */ glGenTextures(1, &img->tex_id); glEnable(GL_TEXTURE_2D); gg_bind_texture(img); Thesecallsestablishpersistentstatedataassociatedwiththetexture.Thisstateinformationincludes:
GL_DECALmeansthatthetextureistobe"pastedover"anyexistingpixelinformation. GL_MODULATEallowsthetexturetobeblendedwithunderlyingpixelinformation. Incompositing,GL_DECALisappropriateforthebackgroundimageandGL_MODULATEforthe foreground. glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexImage2D(GL_TEXTURE_2D, 0, 4, img->width,img->height,0,GL_RGBA, GL_FLOAT, img->fpixels); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, apply); }
24
/**/ void gg_render_quad( image_t *img) { float *pixloc; pixloc = (float *)img->fpixels; glEnable(GL_TEXTURE_2D); glDisable(GL_DEPTH_TEST); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); /* Can't change the size of the visible window here */ /* but the viewport transformation will automagically */ /* map the projected space into the visible window */ glOrtho(0.0, img->width, 0.0, img->height, 0.0, 100000.0);
25
glMatrixMode(GL_MODELVIEW); glPushMatrix(); /* Bind this image's texture to active texture unit */ gg_bind_texture(img); Thiswarptranslatesthecenteroftheimagetotheorigin,scalesbyafactorof0.5,rotatestheimage 45degreesaboutthezaxisandthentranslatesthecenteroftheimagebacktotheoriginallocation. Sincethemodelviewmatrixwillbeappliedtothevertexcoordinatesduringrendering,itismandatory thatanydesiredtransformationbedefinedbeforetheobjectisrendered! #if 1 glTranslatef(img->width / 2.0, img->height / 2.0, 0.0); glRotatef(45.0, 0.0, 0.0, 1.0); glScalef(0.5, 0.5, 1.0); glTranslatef(-img->width / 2.0, -img->height / 2.0, 0.0); #endif
26
Renderingthequad Thefollowingcodeillustrateshowtorenderatexturemappedquad.
glBegin(GL_QUADS); glTexCoord2f(0.0,0.0); glVertex3f(0.0,0.0,0.0); glTexCoord2f(1.0,0.0); glVertex3f(img->width, 0.0 ,0.0); glTexCoord2f(1.0, 1.0); glVertex3f(img->width, img->height, 0.0); glTexCoord2f(0.0, 1.0); glVertex3f(0.0, img->height, glEnd();
0.0);
27
Theresultofthewarpdefinedontheprecedingpagecanbeseenbelow.
28
29
glBegin(GL_TRIANGLES); glColor3f(0.0,1.0,0.0); glTexCoord2f(0.0,0.0); glVertex3f(-1.0,-1.0, 0.0); glColor3f(0.0,1.0,0.0); glTexCoord2f(0.5, 1.0); glVertex3f( 0.0, 1.0 ,0.0); glColor3f(0.0,0.0,1.0); glTexCoord2f(1.0, 0.0); glVertex3f(1.0, -1.0 ,0.0); glEnd();
30
AddingOpenGLeffects OpenGLsupportsfairlycrudeilluminationandfogsystems.Welookatfoghere. Thefirsttwoparametershowthefogginessrespondstochangesinthezcoordinate. Thelasttwocontrolthecolorandthedensityofthefogneartheviewr. static static static static float float float float fmode[1] = {GL_LINEAR}; fend[1] = {800.0}; fcolor[4] = {1.0, 1.0, 1.4, 1.0}; fden[1] = {2.0};
/**/ void gg_fog_on() { glEnable(GL_FOG); glFogfv(GL_FOG_MODE, fmode); glFogfv(GL_FOG_END, fend); glFogfv(GL_FOG_COLOR, fcolor); glFogfv(GL_FOG_DENSITY, fden); }
31
Fogginganimage Sinceanimagehasnodepthcomponent,itissomewhatchallengingtomakefogappearnonuniform. Onewaytoovercomethisistoslanttheimageawayfromtheviewer(ortowardtheviewerdepending ontheviewer'sperspective.) Todothis,wechangetheprojectionasfollows: Wescaletheimagebythesqrt(2)intheydirectionandthenwerotateitaroundthexaxistomakeit tiltawayfromtheviewerintothenegativezspace.Wemustdothescalingifwewanttheimageto stillfillthewindow! glOrtho(0.0, img->width, 0.0, img->height, 0.0, 100000.0); gg_bind_texture(img); glMatrixMode(GL_MODELVIEW); glPushMatrix(); gg_fog_on(); #if 1 glRotatef(-45.0, 1.0, 0.0, 0.0); glScalef(1.0, 1.414, 1.0); #else
32
Perspectiveprojection Perspectiveprojection
InOpenGLtheviewvolumeisdefinedbyviewpoint(orcenterofprojection),thenearclippingplane andthefarclippingplane.Theimageisprojecteduponthenearclippingplane. Theviewpointistheorigin(0,0,0)andtheviewvolumeisdefinedbyacalltoglFrustum() voidglFrustum(GLdouble left,GLdouble right, GLdouble bottom,GLdouble top, GLdouble nearVal,GLdouble farVal); Parameters left,rightSpecifythecoordinatesfortheleftandrightverticalclippingplanes. bottom,topSpecifythecoordinatesforthebottomandtophorizontalclippingplanes. nearVal,farValSpecifythedistancestothenearandfardepthclippingplanes. Bothdistancesmustbepositive. Whenappliedtoanidentityprojectionmatrixleftandrightspecifythexcoordinatesoftheleftand rightedgesoftheprojection,topandbottomspecifyycoordinatesandnearandfararenegativez values. AsmallnearValcreatesawideanglelenswhilealargenearValcreatesatelescopiclense.Youmay havetoexperimenttoachievetheeffectthatyouwant. 33
Viewinganimagewithperspectiveprojection Tomapanimageontothenearclippingplaneitshouldbegiventhedimensionsoftheimage.Oneway todothisisasshown. glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glFrustum(0.0, img->width, 0.0, img->height, 10.0, 10000.0); Ifitisdesiredtocompositeforegroundobjectswiththebaseimageabetterchoiceoffrustum: glFrustum(-img->width / 2, img->width / 2, -img->height / 2.0, img->height / 2.0, 10.0, 10000.0); Thelocationofthefrustumdoesnotaffectthelocationoftheviewpoint,sointhefirstfrustumyouwill belookingupandrightattheimagefromthelowerleftcornerwhereinthesecondyouwillbelooking directlyattheimagefromthecenter. Otherchoicesmightincludelocatingtheviewpointnearthebottominsteadofatthecenterofthe backgroundimage. glFrustum(-img->width / 2, img->width / 2, -img->height / 10.0, img->height * 9.0 / 10.0, 10.0, 10000.0); Regardlessofwhereyoulocationthenearclippingplaneitisnecessarythattheimagebelocatedon thenearclippingplaneandmappedtothefrustum.Thiscanbedonebyaddingtheappropriate translationtotheprojectionormodelviewmatrixorsupplyingthezcoordinatewhiledrawingthequad. #define Z_PLANE -5.0
34
Renderingtheimage Settinguptheprojection #define Z_PLANE -16 /**/ void gg_perspective_quad( image_t *img) { glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glFrustum(-img->width / 2, img->width / 2, -img->height / 10.0, 9 * img->height / 10.0, -Z_PLANE, 20000.0); glEnable(GL_TEXTURE_2D); glDisable(GL_DEPTH_TEST);
35
Renderingtheimage
Ifthepropertranslationhasbeenappliedtotheprojectionmatrix,thentheimagecanberenderedjust asbefore.Ifthetranslationisomitted,thenitseffectsmustbeincorporatedintothecallsto glVertex3f() #if 0 glScalef(0.5, 0.5, 1.0); glTranslatef(-img->width / Z_PLANE glRotatef(-0.45, 1.0, 0.0, #else glTranslatef(-img->width / Z_PLANE #endif glBegin(GL_QUADS); glTexCoord2f(0.0,0.0); glVertex3f(0.0,0.0,0.0); glTexCoord2f(1.0,0.0); glVertex3f(img->width, 0.0 , 0.0); glTexCoord2f(1.0, 1.0); glVertex3f(img->width, img->height, 0.0); glTexCoord2f(0.0, 1.0); glVertex3f(0.0, img->height, glEnd();
0.0);
36
Compositing Perspectiveprojectioncanbeusedtoplaceanobjectatatargetlocationinanimageandthen automagicallyitscaletoitszcoordinate. void gg_perspective_fg( image_t *img, image_t *fg, double tx, double ty, double tz) { glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glFrustum(-img->width / 2, img->width / 2, -img->height / 2.0, img->height / 2.0, -Z_PLANE, 600.0); glEnable(GL_TEXTURE_2D); glDisable(GL_DEPTH_TEST); gg_bind_texture(fg); glPushMatrix(); glTranslatef(tx, ty, tz);
37
Theforegroundobjectisdrawnjustasbefore... glBegin(GL_QUADS); glTexCoord2f(0.0,0.0); glVertex3f(0.0,0.0,0.0); glTexCoord2f(1.0,0.0); glVertex3f(fg->width, 0.0 ,0.0); glTexCoord2f(1.0, 1.0); glVertex3f(fg->width, fg->height, 0.0); glTexCoord2f(0.0, 1.0); glVertex3f(0.0, fg->height, glEnd(); glPopMatrix(); glFlush(); glMatrixMode(GL_PROJECTION); glPopMatrix(); }
0.0);
38