Você está na página 1de 38

ManipulatingimageswithOpenGL WehavesofartreatedOpenGLasa"blackbox"mechanismfordisplayingimages.Wewillnowlook ataspectsofhowitmaybeusedinwarping,tiling,andcompositingimages. OpenGLisinherentlydesignedfor3Dgraphics.Assuchitemploysprojectiontorender3Dobjects upona2DScreen.

TwoclassesofprojectionaresupportedbyOpenGL Perspectiveprojection

Theprojectionisdefinedby:

TheCenterofProjection(COP)thereddot. TheViewplanethegrayplane TheFrontandBackClippingplanestheblueplanes.

anditscharacteristicsinclude:

Anobjectisvisibleifandonlyifitliesinthesolidfrustumdefinedbytheclippingplanesand theblacklines(includingtheonethatismissing!).Thisspaceiscalledtheviewvolume. AanobjectwillappearontheviewplanewherelinesoriginatingattheCOPandpointsonthe objectintersecttheViewplane. Thusiftwoobjectsofequalheightarelocatedinfrontofandbehindtheviewplane,theonein frontwillappearlarger.

IntheOpenGLimplementationtheviewplaneandnearclippingplanescoincideandsovisibleimage isactuallyprojecteduponthenearclippingplane. 1

Orthographicprojection Orthographicprojectionisaspecialcaseofparallelprojection.

Theprojectionisdefinedby:

TheViewplanethegrayplanewithnormalvectorVPNwhichpointsinthegeneraldirection oftheviewer. TheDirectionofProjection(DOP)whichisVPN(reversedviewplanenormal)for orthographicprojections. TheFrontandBackClippingplanestheblueplanes.

anditscharacteristicsinclude:

Anobjectisvisibleifandonlyifitliesintherectangularsoliddefinedbytheclippingplanes andtheblacklines(includingtheonethatismissing!).Thisareaisknownastheviewvolume. Aanobjectwillappearontheviewplanewherelinesparelleltotheedgesoftherectangular solidandpassingthroughpointsontheobjectintersecttheViewplane. Thusiftwoobjectsofequalheightarelocatedinfrontofandbehindtheviewplane,theywill appeartobethesamesize.

Thesimplestorthographicprojection OpenGLusesastandardrighthandedcoordinatesystem y x z ThesimplestprojectionwhichisalsothedefaultprojectioninOpenGLis


DOP=(0,0,1)(negativezaxis) VPN=(0,0,1)(positivezaxis) Viewplane=z=0 Frontclippingplane=z=1 Rearclippingplane=z=1 Visibleareaoftheviewplaneisthe2x2quad(1,1.0),(1,1.0),(1,1.0),(1,1,0)thatis centeredattheorigin.

Thustheviewvolumeisacubecenteredattheoriginandhavingedgesoflength2anditseight verticesarelocatedat(x=+/1.0,y=+/1.0,z=+/1.0).

Theclippingandprojectionalgorithm Theprocessofclippingandprojectionisthenextremelysimple.Givenapoint(x,y,z) Clipping


Ifz>1orz<1thepointisdiscarded Ifx>1orx<1thepointisdiscarded Ify>1ory<1thepointisdiscarded

Projection

Theprojectionofthepoint(x,y,z)thatsurvivesclippingissimply(x,y,0);

InOpenGLandothersanegraphicssystems,arbitraryparallelprojectionsaretransformedintoa simpleprojectionsuchasthisoneviaaseriesofaffinetransformationsinhomogenouscoordinatesin 3Dspacethatwillmapanarbitraryviewvolumeintoacanonicalviewvolumesuchastheone describedabove. Sincethetransformationmapstheverticesofthearbitraryviewvolumetothecanonicalviewvolumeit alsomapstheverticesofobjectsinthescenetotheproperrelativelocationsinthecanonicalview volume. Therefore,aftertheprojectivetransformationisappliedclippingandprojectionaretrivial.

TheOpenGLgeometrypipeline InOpenGL,positionsin3Dspacearerepresentedasusinghomogeneouscoordinates(x,y,z,1). Whenanobjectistoberendered,thecoordinatesofitsverticesaretransformedbyapplicationofa seriesof4x4matricesanalogoustothose3x3matricesthatwehaveusedin2D. InournotationavertexVistransformedasfollows [Viewport][Projection][Modelview]V where[Viewport][Projection][Modelview]represent4x4matrices. Therolesofthetransformationsroughlyareasfollows:

[Modelview]Placesanobjectatthecorrectlocationinthesceneinworldcoordinates. Hence,itiscommontousedifferentmodelviewtransformationsforeachobjectorcomponent ofanarticulatedobjectthatistobeplaced. [Projection]Transformsthespecified(arbitrary)viewvolumeintothesystem'scanonical viewvolumeandprojectsthepoint(perspectiverenormalizationisrequiredforperspective projections) [Viewport]Asimplescalingtranformationthatmapstheunitsizedprojectionwindowtothe pixeldimensionsofthescreenwindow.

OpenGLprovidesasetofprimativesincludingRotate,Translate,andScalethatmaybeusedto transformtheModelviewandProjectionmatrix. TheViewportscalingtransformissetupbytheOpenGLsystemwhenawindowisinitiallycreatedand whenitisresized.

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

left, right, bottom, top, nearVal, farVal);

ThiscalltoGlOrthocreatesthefollowingProjectionmatrix.Recallthatthemissionofthematrixisto mapthespecifiedviewvolbacktothecanonicalviewvolume. 2 ------right - left

tx

2 --------top - bottom

ty

-2 ---------far - near 0 0

tz

0 Where
tx = -(right + left) ------------right - left

ty =

-(top + bottom) -----------top - bottom

tz = -(far + near) ------------far - near

Notethatthesamedenominatorsappearinthetranslationandscalingfactors. Example: Supposeleft=4andright=6. Thentx=(4+6/2=5andsx=sy=1. Thusleftismappedto1andrightto+1. Thezcoordinatemadnessappearstooccurbecausemovingawayfromtheviewerismovinginthe negativezdirection.Supposefar=1andnear=0.Thismatrixwillflipnegativezcoordinatesto postiveandsoanyvaluebetween0andfarwillnotbeclipped. Exercise:Wheredoes(right,top,far)mapundertheprojection?

Creatingawindowforviewinganimage OpenGLimplementsastatemachineinwhichvariousstatevariablescanbesetandretaintheirvalues untilexplicitlychanged.Thevaluesofstatevariablesareassociatedwithaspecificdrawingcontext (i.e.window)andsocannotbesetuntilawindowiscreated.

/**/ 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

TransformationsinOpenGl Matrixmanagement TransformsinOpenGLdoin3Dpreciselywhatwehavebeendoingin2D.Theymultiplythecurrent matrix(ProjectionorModelview)ontherightbythematrixdefinedbythetransform.Thatis,ifthe currentmatrixisMandthetransformdefinesthematrixTthentheresultofcallingthetransformisin matrixnotation. M=MT Therefore,inOpenGLifwewantto


translateanobject,presentlylocatedat(30,20,0)totheorigin, rotateitabout30degreesthezaxisand thenscaleto1/2size..

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

Renderingapixmapimage WehavebeenusingthefunctionglRasterPos2i()andglDrawPixels()torenderanimage. ThecurrentmodelviewtransformisappliedtothelocationspecifiedglRasterPos2i(),andthenthe pixelsaredrawninarectanglewithlowerleftcorneratthe(possiblytransformed)locationspecified. Notethatthe3rdparametertoglDrawPixels()specfiesthenumberofchannels,andtheforththeformat ofthepixelintensity(GL_FLOAT,GL_UNSIGNED_BYTE);

{ glRasterPos2i(img->rx, img->ry); glDrawPixels(img->width, img->height, GL_RGBA, GL_FLOAT, img->fpixels); }

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:

imgholdstheaddressofthebackgroundimage(hmbay.ppm). foregroundholdstheaddressoftheforegroundimage(darth.ppm)thathasalreadybeen thresholdedaspreviouslydescribedsothatthealphacomponentsofbluescreenpixelsare1.0. eachofthe3callstogg_render_foreground()rendersseparateinstanceoftheforeground image.

/**/ 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

Creatingatexture ThecalltoglBindTexture()bindsthetexturenameimg>texidtotheactivetextureunit. void gg_bind_texture( image_t *img) { glBindTexture(GL_TEXTURE_2D, img->tex_id); }

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:

theformat,dimensions,andlocationofthepixmap(img>fpixels), texturepixelfilteringtechnique,and howthetextureistobeappliedtotheimage.

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

Renderingatexturemappedquad Thisfunctionwillrenderatexturedquadusingaparallelprojection.Notethatwecanpreservethe stateoftheprojectionmatrixbypushingitonthestackbeforewesetupourownprojection. Importantelementstonoteare:

Pushingtheexistingmatrixonthestackdoesnotchangeit.Ifwewanttostartwithanicefresh identitymatrixwemustcallglLoadIdentity() Anytimewepushamatrixontothestackwemustremembertopopitbeforeleavingthe function. TheglOrthotransformbelowwillclippositivezcoordinatesbutthosebetween0and100000.0 willbevisible.

/**/ 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

Drawingthequad Herewedrawasinglequadwhosedimensionsarethoseoftheimage.Thezcoordinateofeachofits verticesissetto0.0.Foreachquadvertexwemustalsosupplythecoorespondingtexturecoordinate. Notethattexturecoordinatespaceisnormalizedtotherange[0.0,1.0]. ThecallstoglPushMatrix()andglPopMatrix()arenecessaryforproperfunctioning.Withoutthemthe warpingtransformswouldaccumylateeachtimethewindowwasoccludedandthenredrawnandsoon theimagewoulddisappear.

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.

Thefourverticesofthequadmustbespecifiedintheworldcoordinatesystemdefinedbythe glOrtho()function. Thetexturecoordinatesarefractionalcoordinatesanalogoustothoseweusedinthemesh warp. Asspecifiedbelowtheymaptheentiretexturetothequadbeingdrawn. Whathappensifvalues<1.0or>1.0arespecified??

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);

Itisextremelyimportanttokeepmatrixpushandpopsproperlysynchronized. glPopMatrix(); // pop modelview

glMatrixMode(GL_PROJECTION); glPopMatrix(); // pop projection glFlush(); }

27

Theresultofthewarpdefinedontheprecedingpagecanbeseenbelow.

28

Wecanalsowarpin3Dspace.Replacingthe4linewarponthepreviouspagebythisonewhich rotatestheimageabouttheyaxis.Producestheimageshownbelow.Sinceaparallelprojectionisin use,theapparenteffectisjusttoshrinkthewidthbyafactorof1/sqrt(2.0); glRotatef(45.0, 0.0, 1.0, 0.0);

29

Applyingatexturetoatriangle Sincethe2Dtextureisrectangularinshape,aformofbilinearmappingmustbeusedtoapplyitto triangles.


Theprogrammerisresponsibleforcomingupwithsensiblemappings. Inthiscasetheappearanceoflookingthroughatriangularwindowattheimagewillbe produced. Ifthe0.5inthehighlightedlineischangedto1.0,thewindowwillstillbeatriangle,butthe upperrightcornerofthetexturewillappearatthetopofthetriangleandthetexturewillbe "warped".

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

glTranslatef(-img->width / 2.0, -img->height / 2.0, Z_PLANE - 0.01); Thefudgefactorof0.01issufficienttoensurethatnumericalimprecisionintheprojectiondoesn't causetheimagetoenduponthewrongsideoftheclippingplane!

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();

2.0, -img->height / 2.0, 0.01); 0.0); 2.0, -img->height / 2.0, 0.01);

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

Você também pode gostar