Tietokonegrafiikka / perusteet Ako/T-111.300/301 4 ov / 2 ov OpenGL 1 Yleistä harjoituksista OpenGL:n toiminta Primitiivit Kuvapuskurit Koordinaatistot ja projisointi Transformaatiot ja matriisit Valaistus ja materiaalit GLUT Sisällys Marko Myllymaa 06/04 OpenGL / 1 OpenGL / 2 Harjoitukset Pieniä harjoituksia 5 kappaletta Lopuksi isompi harjoitus Pikkuharjoituksista saa pisteitä 0-4, eli yhteensä 20 Lopputyöstä saa pisteitä 0-20 Lopputyön arvostelu: näyttävyys 0-6p laajuus ja vaativuus 0-5p koodi 0-3p dokumentti 0-3p UI+muuta 0-3p Pienet harjoitustyöt OpenGL/GLUT C/C++ (pohjakoodi C:tä) ympäristönä O2 ja Windows/Dev-Cpp Tehdään yksin DL viikon välein, alkaen 14.6. Palautetaan mailitse osoitteeseen ti111300@niksula.hut.fi Kaikista kohdista on saata vähintään 1 piste Koko kurssin arvosana määräytyy harjoitustyöarvosanan ja tenttiarvosanan keskiarvona OpenGL / 3 OpenGL / 4 Pienet harjoitustyöt 1.harjoitus Objektien luominen, väritys ja liikuttaminen Kameran liikuttaminen 2.harjoitus Display listat Erilaiset valot 3.harjoitus Teksturointi Alpha blendaus 4.harjoitus Tekstit Animaatio Kameran ohjaus hiirellä 5.harjoitus Objektien valitseminen hiirellä varjot OpenGL / 5 Materiaalia OpenGL Programmin Guide Neider/Davis/Woo Addison Wesley O2:sten Insight-kirjat Programming Guide Komentona insight -n Web www.opengl.org www.opengl.org/developers/documentation/glut.html www.mesa3d.org nehe.gamedev.net www.cygwin.com OpenGL / 6 1
Esimerkkejä ~ti111300/o2/opengl-aloita-taalta tutor: hyviä demoja util: sekalaisia hyödyllisiä ohjelmanpätkiä ~ti111300/o2/opengl-esim www.opengl.org/developers/code tutoriaaleja ja esimerkkikoodia nehe.gamedev.net tutoriaaleja OpenGL ohjelma OpenGL tekee ainoastaan renderöinnin Event loopit, ikkunan avaaminen, syöttölaitteiden lukeminen, ei kuulu OpenGL:ään GLUT (OpenGL Utility Toolkit) tarjoaa ikkunakontrollin ja syöttölaitteiden lukufunktiot GLU (OpenGL Utility Library) tarjoaa muutamia muutamia geometrisiä malleja, projektiofunktioita, glulookat(), OpenGL / 7 OpenGL / 8 Vertex Data Display List OpenGL Pipeline Evaluaattorit Rasterointi Vertex-operaatiot Primitiivit Fragmentointioperaatiot Näyttö OpenGL tilakone Kaikki renderöinti tapahtuu ns. Nykyisessä tilassa 100 erilaista tilamuuttujaa Kaikki tilamuuttujat globaaleja Väri, nykyinen textuuri, transformaatio matriisi, Disable/Enable liput Pixel Data Data (cached tai evaluoitu) Transform/ valaistus leikkaus Pikselioperaatiot Pikselioperaatiot Tekstuurit Teksturointi Rasterointi Z-puskuri stencil blending Framepuskuri glcolor3f(1.0,0.0,0.0); glenable(gl_depth_test); gltranslate(x,y,z); glget*(glstate, *parameter); glisenabled(mode); glpushattrib(attributegroup); glpopattrib(attributegroup); CPU/muisti Laitteisto/grafiikkapuskurit OpenGL / 9 OpenGL / 10 Geometriset primitiivit Hyvät ja huonot polygonit GL_POINTS GL_TRIANGLES GL_POLYGON GL_LINES GL_LINE_STRIP GL_LINE_LOOP V1 GL_TRIANGLE_STRIP v5 GL_TRIANGLE_FAN GL_QUADS v7 v6 v5 GL_QUAD_STRIP v6 v5 v7 Hyviä: konveksit Huonoja: konkaavit, reikiä Default: glfrontface(gl_ccw); OpenGL / 11 OpenGL / 12 2
Polygonin etupuoli Polygonin etupuoli Vertexien järjestys Piirto moodi: void glpolygonmode(glenum pinta, Glenum moodi); pinta: GL_FRONT_AND_BACK, GL_FRONT, GL_BACK moodi: GL_POINT, GL_LINE, GL_FILL glfrontface(gl_ccw); Taustapintojen poisto (backface culling): glcullface(gl_back); glenable(gl_cull_face); (moodi = GL_FRONT, GL_BACK tai glfrontface(gl_cw); GL_FRONT_AND_BACK) glfronface(gl_cw); glpolygonmode(gl_front, GL_FILL); glpolygonmode(gl_back, GL_LINE); glbegin(gl_triangles); glcolor3f(0.0,0.7,0.0); glvertex3f(0.25,0.0,0.0); glvertex3f(0.25,1.0,0.0); glvertex3f(1.0,0.0,0.0); glcolor3f((0.0,0.0,0.7); glvertex3f(-0.25,0.0,0.0); glvertex3f(-0.25,1.0,0.0); glvertex3f(-1.0,0.0,0.0); glend(); V2 +Z V1 V0 +Y V0 V1 V2 +X Huomaa koordinaatisto! OpenGL / 13 OpenGL / 14 Vertexit glbegin():n ja glend():n välissä määritettävät primitiivit (pisteet, kolmiot, kolmioviuhkat, ) Vertexissä oleva informaatio, ei vain paikka; Vertexit glbegin():n ja glend():n välissä voi olla vain rajoitettuja OpenGL kutsuja Muuta koodia siellä voi olla: glvertex*() glcolor*() glindex*() glnormal*() gltexcoord*() glmultitexcoord*arb() glmaterial*() gledgeflag*() glarrayelement() glevalcoord*() glevalpoint() glcalllist() glcalllists() vertexin koordinaatit nykyinen väri nykyinen väri-indexi normaalivektorin koordinaatit tekstuurikoordinaatit tekstuurikoordinaatit(multiteksturointi) materiaaliominaisuudet kontrolloi reunojen piirtoa haetaan vertexitaulukosta dataa generoi koordinaatteja generoi koordinaatteja suorittaa display listan suorittaa display listoja Glint circle_points = 8; glbegin(gl_line_loop); for(i = 0; i < circel_points; i++) { angle = 2*PI*I/circle_points; glvertex2f(cos(angle), sin(angle)); } glend(); OpenGL / 15 OpenGL / 16 Esimerkki #include <mitätarvitaan.h> main() { OpenWindowPlease(); glclearcolor(0.0,0.0,1.0,0.0); glclear(gl_color_buffer_bit); glortho(-1.0,1.0,-1.0,1.0,-1.0,1.0); glcolor3f(0.0,1.0,0.0); glbegin(gl_polygon); glvertex2f(-0.5,-0.5); glvertex2f(-0.5,0.5); glvertex2f(0.5,0.5); glvertex2f(0.5,-0.5); glend(); glflush(); KeepTheWindowOnTheScreen(); } Stencil buffer maskaus 1 bitti tai enemmän OpenGL:n grafiikkapuskurit Accumulation buffer kumulatiivinen rendaus Depth buffer (Z buffer) syvyysinfo: näkyvyys 16..32 bittiä Frame buffer RGBA (4*8bittiä) tupla: 2 stereo: 2+2 alpha-arvo: blendaus läpinäkyvyys Puskureiden bittimäärä riippuu implementaatiosta OpenGL / 17 OpenGL / 18 3
Puskureiden tyhjennys Muista tyhjentää puskurit ennen rendaamista Puskurit saattavat sisältää mitä tahansa ennen tyhjennystä aseta tyhjennysarvot frame bufferille: (0.0,0.0,0.0,0.0) Z bufferille: (1) (maksimi etäisyys) defaultit yleensä järkeviä tyhjennä puskurit tyhjennys pitää tehdä ennen jokaisen kuvan piirtoa esim: glclearcolor(0.0,0.0,0.0,0.0); glcleardepth(1.0); glclear(gl_color_buffer_bit GL_DEPTH_BUFFER_BIT); Tuplapuskurointi Välttääksesi rendauksen näkymistä ja välkkymistä, käytä tuplapuskurointia Rendataan taustalla olevaan puskuriin ja vaihdetaan luettavaa puskuria Stereo-ohjelmassa tarvitaan kaksi puskuria molemmille silmille redraw(void) { glclear(gl_color_buffer_bit GL_DEPTH_BUFFER_BIT); glcalllist(dinosaur); glutswapbuffers(); } main(int argc, char **argv) { glutinit(&argc, argv); glutinitdisplaymode(glut_rgb GLUT_DOUBLE GLUT_DEPTH); glutdisplayfunc(redraw); glutmainloop(); OpenGL / 19 OpenGL / 20 Pikseli testit Piirrettävien pikselien valinta perustuu dataan erilaisissa puskureissa taikka muihin sääntöihin Scissor test rajoitetaan rendau nelikulmaiseen alueeseen Pikseli testit Puskuritestien toiminnallisuus voidaan valita Oletusarvot päästävät pikselit läpi, paitsi syvyystestissä gldepthfunc(gl_less); glalphafunc(gl_always); glstencilfunc(gl_always,0,255); GL_NEVER, GL_ALWAYS, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL Stencil test maskaus puskuri Depth test näkyvyys testi Alpha test valinta perustuu läpinäkyvyyteen Disabloi syvyys ja alpha testi, kun blendaat! void glstencilop(gl_keep, GL_KEEP, GL_KEEP); // fail, zfail, zpass GL_KEEP, GL_ZERO, GL_REPLACE, GL_INCR, GL_DECR, GL_INVERT glscissor(x, y, width, height); Muista enabloida testit: glenable(gl_depth_test); glenable(gl_stencil_test); glenable(gl_alpha_test); glenable(gl_scissor); OpenGL / 21 OpenGL / 22 3D katselu Kaikki 3D transformaatiot voidaan laskea homogeenisillä 4x4 matriiseilla OpenGL:ssä on kaksi matriisipinoa: katselumatriisit (modelview) projektiomatriisit (projection) Katselumatriisipinossa vähintää 32 kerrosta Projektiomatriisipinossa vähintään 2 kerrosta glmatrixmode(gl_modelview); glmatrixmode(gl_projection); 3D katselu OpenGL:n ja GLU kirjaston funktioita matriisipinojen käsittelyyn: Initialisoidaan nykyinen matriisi (katse negatiivisen Z-akselin suuntaan) Transformaatiomatriisit objektion manipuloimiseksi: gltranslate*(x,y,z); glrotate*(a,x,y,z); glscale*(x,y,z); Asetetaan projektio: glfrustum(left,right,bottom,top,near,far); gluperspective(field-of-view, aspect, near, far); glortho(left,right,top,bottom,near,far); OpenGL / 23 OpenGL / 24 4
3D katselu Objektin saaminen ruudulle tarvitsee sarjan tranformaatioita eri koordinaatistojen välillä: Vertexit Objektin koordinaatit Kameran koordinaatit Ja tämä tehdään jokaiselle vertexille Perspektiivijako Normalisoidut laitekoordinaatit Ikkunakoordinaatit Katselumatriisi Projektiomatriisi Katselutransformaatio Leikkauskoordinaatit Projektiot Perspektiiviprojektio gluperspective(fovy, aspect, znear, zfar); glfrustum(left, right, bottom, top, near, far); Orthogonaaliprojektio glortho(left, right, bottom, top, near, far); Orthogonaaliprojektio määrittää vain katselutilavuuden, perspektiivijakoa ei ole käytössä Muista käyttää projektiomatriisia, kun kutsut näitä! glmatrixmode(gl_projection); OpenGL / 25 OpenGL / 26 Kameran sijoittaminen Ensin vaihdetaan katselumatriisiin ja alustetaan se: glmatrixmode(gl_modelview); Käytä glulookat:iä tuottamaan katselumatriisi haluamallesi katselukulmalle (tai käytä glrotate:a ja gltranslate:a) glulookat(eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz); Oletus on negatiivisen Z-akselin suuntaan/pitkin Translaatio Talleta nykyinen matriisi Tee transformaatiot ennen vertexien syöttämistä glmatrixmode(gl_modelview); glulookat(3,3,8, 0,0,0, 0,1,0); glpushmatrix(); gltranslatef(0.0,0.0,3.0); glutwiresphere(1.0,20,16); glpopmatrix(); OpenGL / 27 OpenGL / 28 Rotaatio Alusta projektiomatriisi: glmatrixmode(gl_projection); gluperspective(45,1.77,1,30); Katselu - yhteenveto Rotaatio ensin glrotatef(45,0,1,0); gltranslatef(0,0,3); Translaatio ensin gltranslatef(0,0,3); glrotatef(45,0,1,0); alusta katselumatriisi: glmatrixmode(gl_modelview); Sijoita kamera (glulookat tai gltranslate ja glrotate) Sijoita objektit maailmaan: talleta nykyinen matriisi: glpushmatrix() muokkaa matriisia: gltranslate(), glrotate() piirrä objekti palaa aiemmin talletettuun matriisiin: glpopmatrix() OpenGL / 29 OpenGL / 30 5
Värit Nykyinen väri on tila, jota voidaan muuttaa haluttaessa Sheidatussa rendauksessa pikselin lopullinen väri riippuu monesta parametristä RGBA red, green, blue, alpha oletus esitysmuoto valaistus, blendaus, teksturointi yms. toimivat intuitiivisesti glutinitdisplaymode(glut_rgba); glcolor(0,1,0); Indeksoitu lista indeksoituja värejä alijoukko koko väriavaruudesta renderöinnissä saattaa tulla ongelmia indeksoiduilla väreillä ei suositella glutinitdisplaymode(glut_indexed); Sävytys (shading) Lasketaan (aproksimoidaan) pinnalta lähtevän valon määrä OpenGL:ssä on kaksi tapaa täyttää polygoni: FLAT polygoni täytetään tasaisella värillä väri on yhden vertexin väri SMOOTH värit lasketaan jokaisessa vertexissä lasketut värit interpoloidaan polygonin sisäpuolisille pisteille (Gouraud shading) Huom. Käytä glcolor():ia vain ilman valoja ja materiaaleja OpenGL / 31 OpenGL / 32 Valaistus ja materiaalit Objektin muotoja ei näy ilman valoja, pallo vaikuttaa ympyrältä Sama objekti saadaan näyttämään täysin erilaiselta erilaisilla valoilla ja materiaaleilla Täydellistä valaistusyhtälöä ei ole Yksinkertainenkin valaistus ja materiaalien käyttö voi osoittautua riittäväksi Valot määrittävät emission, materiaalit määrittävät haijastuksen Ambient tasainen kaikkialla Diffuse valolla on suunta Valon komponentit Specular valolla on suunta, aiheuttaa heijastukset Materiaaleilla on samat ominaisuudet sekä vielä emissiivinen materiaali OpenGL:ssä nämä ovat täysin toisistaan riippumattomat OpenGL / 33 OpenGL / 34 Valaistuksen suunnittelu Määritä vertexeille normaalit heijastuskulmat lasketaan niiden avulla Luo ja sijoita valonlähteet käytä mahdollimman vähän valonlähteitä Määritä ambientti valo sekä yleinen valaistusmalli local viewer <> infinte viewer Määritä objektille materiaalit pyri todellisuuteen Pinnan normaalit Normaalit ovat vertexien ominaisuus OpenGL:ssä ei ole pintoja Vertexinormaalit ovat tasaiselle objektille vakiot, yleensä kuitenkin objektit ovat epätasaisia/kaarevia.. Kaarevilla objekteilla normaalit muuttuvat joka vertexillä Polygonipinnoilla on hyvä käyttää normaalien keskiarvoa: n[0]=(n1[0]+n2[0])/2.0; n[1]=(n1[1]+n2[1])/2.0; n[2]=(n1[2]+n2[2])/2.0; glnormal3f(n[0],n[1],n[2]); glbegin(...); glend(); OpenGL / 35 OpenGL / 36 6
Valon ominaisuudet OpenGL tukee vähintään 8 valonlähdettä Ominaisuuksia: väri, paikka, suunta, kulma, void gllight{if}[v](glenum light, Glenum pname, TYPEparam); Parametrin nimi Oletusarvo Tarkoitus GL_AMBIENT (0.0,0.0,0.0,1.0) ambient väri, RGBA GL_DIFFUSE (1.0,1.0,1.0,1.0) diffuusi väri, RGBA GL_SPECULAR (1.0,1.0,1.0,1.0) kiiltoväri, RGBA GL_POSITION (0.0,0.0,1.0,0.0) (x,y,z,w) paikka GL_SPOT_DIRECTION (0.0,0.0,-1.0) (x,y,z) kohdevalon suunta GL_SPOT_EXPONENT 0.0 kohdevalokerroin GL_SPOT_CUTOFF 180.0 kohdevalon valokeilan leveys GL_CONSTANT_ATTENUATION 1.0 vakio vaimentuminen GL_LINEAR_ATTENUATION 0.0 lineaarinen vaimentuminen GL_QUADRATIC_ATTENUATION 0.0 neliöllinen vaimentuminen Yleiset valaistusmallit Ambientti taustavalo: Glfloat ambient[] = {0.1,0.1,0.1,1.0}; gllightmodelfv(gl_light_model_ambient, ambient); Hypoteettisen katsojan paikka: FALSE:lla saa nopeammat valaistuslaskut gllightmodeli(gl_light_model_local_viewer,gl_true); gllightmodeli(gl_light_model_local_viewer,gl_false); Kaksipuoleinen valaistus yksipuoleinen on luonnillisesti nopeampaa gllightmodeli(gl_light_model_two_side,gl_true); gllightmodeli(gl_light_model_two_side,gl_false); Oletusarvot pätevät vain valolle GL_LIGHT0 Muille valoille GL_DIFFUSE ja GL_SPECULAR ovat oletuksena (0.0,0.0,0.0,1.0) OpenGL / 37 OpenGL / 38 Materiaalin ominaisuudet Materiaaleilla on pääosin samat ominaisuudet kuin valoillakin, sekä emissiivisyys vielä lisäksi Emissiivisyys ei kuitenkaan vaikuta valaistuslaskentaan void glmaterial{if}[v](glenum face, Glenum pname, TYPEparam); Parametrin nimi Oletusarvo Tarkoitus GL_AMBIENT (0.2,0.2,0.2,1.0) materiaalin ambientti väri GL_DIFFUSE (0.8,0.8,0.8,1.0) diffuusi väri GL_AMBIENT_AND_DIFFUSE ambientti ja diffuusi väri GL_SPECULAR (0.0,0.0,0.0,1.0) kiiltoväri GL_SHININESS 0.0 kiiltokerroin GL_EMISSION (0.0,0.0,0.0,1.0) emissiivinen väri GL_COLOR_INDEXES (0,1,1) ambientti, diffuusi ja kiiltovärien indeksit Voit laittaa ambientin ja diffuusin värin seuraan nykyistä väriä: glenable(gl_color_material); glcolormaterial(gl_front_and_back, GL_AMBIENT_AND_DIFFUSE); GLUT GLUT OpenGL Utility Toolkit Tekijä: Mark J. Kilgard Ikkunointijärjestelmästä riippumaton OpenGL API (C) Tapahtumien hallintaa rekisteröimällä callback funktioita Voi hallita montaa OpenGL-ikkunaa Idle looppi Syöttölaitteet Pop-up menut 3D primitiivejä: torus, pallo, kartio, teekannu, Overlay Fontit Sekalaisia apufunktioita OpenGL / 39 OpenGL / 40 Esimerkki OpenGL / 41 7