OpenGL/Geometristen alkioiden piirtäminen
Jopa Max Paynen kaltaisten tietokonepelien grafiikka koostuu enimmäkseen kolmioista. Kolmio on ehkä tärkein OpenGL:n geometrisistä alkioista eli primitiiveistä. Nämä geometriset alkiot ovat kaikki, mitä OpenGL osaa piirtää, eikä niitä ole montaa.
Piirtäminen voidaan jakaa kolmeen vaiheeseen:
- OpenGL-ikkunan (ja mahdollisten muidenkin näyttömuistipuskurien) tyhjennys
- piirtäminen
- piirtokäskyjen näyttäminen kuvaruudulle
Ensimmäinen ja viimeinen ovat yksinkertaisia perustoimintoja. Piirtäminen on huomattavasti monipuolisempaa.
Puskureiden tyhjennystä
muokkaaTarkastellaan piirtoesimerkkiä, joka on jaettu edellä mainittuihin vaiheisiin:
/* tyhjennys */ glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT);
/* piirto */ glBegin(GL_TRIANGLES); glColor3ub(255, 255, 255); glVertex2f (-1.0, -1.0); glVertex2f (1.0, -1.0); glVertex2f (0.0, 1.0); glEnd();
/* pakotetaan käskyt grafiikkayksikölle */ glFlush(); /* kaksoispuskuroinnissa puskurien vaihto (esim. glutSwapBuffers) */
glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) käsiteltiin loppuun jo edellisessä luvussa: se asettaa tyhjennysvärin RGBA-väriarvot liukulukuina, jotka rajoitetaan välille [0, 1].
glClear(GLbitfield bittikenttä) tyhjentää näyttömuistipuskureita. Parametri on bittikenttä eli ’|’-operaattorilla yhdistetty kokoelma vakioita.
- Väripuskuri GL_COLOR_BUFFER_BIT määrää ikkunassa näkyvän kuvan.
- Syvyyspuskuria GL_DEPTH_BUFFER_BIT (engl. myös z-buffer) käytetään piilottamaan toisten takana olevia esineitä pikselintarkasti.
- Sapluunapuskuri GL_STENCIL_BUFFER_BIT ja kertymäpuskuri GL_ACCUM_BUFFER_BIT (engl. accumulation buffer) ovat erikoisefektejä kuten heittovarjoja ja reunanpehmennystä varten.
Puskurit täytyy ottaa käyttöön jo ikkunaa luodessa. GLUT-kirjastossa tämä tehdään glutInitDisplayMode-käskyllä.
Piirtämistä ei välttämättä suoriteta heti: joissakin ympäristöissä komennot kulkevat lähiverkon yli, ja vasta riittävän suuri verkkopaketti lähetetään. Komento glFlush() pakottaa siihen astiset piirtokomennot grafiikkayksikön suoritettavaksi. Se ei odota, että nämä käskyt olisivat valmiit. Käytännössä flushing on tarpeen vain, jos piirtäminen ei ole kaksoispuskuroitua: puskurien vaihto tekee sen automaattisesti. Kaksoispuskurointia käsitellään animaation yhteydessä.
glFlush-komennolla on myös sisar glFinish(), joka odottaa että kaikki käskyt ovat suoritettu. Sitä käytetään lähinnä mittaamaan piirtonopeutta, kun sovellusta halutaan optimoida tehokkaammaksi: Ilman glFinish-komentoa suuri piirto-operaatio vaikuttanee toteutuvan hetkessä, vaikka oikeasti sitä ei ole vielä edes lähetetty grafiikkayksikölle!
Piirtäminen
muokkaaKomento glBegin(alkio) aloittaa piirtämään alkio-tyyppisiä geometrisiä alkioita. Se myös asettaa OpenGL:n piirtotilaan, jossa saa käyttää vain rajallistaa osaa OpenGL-komentoja. Niistä tärkein on nurkkapisteen sijainnin määrittelevä glVertex. Piirtäminen lopetetaan komennolla glEnd().
Geometriset alkiot
muokkaaSeuraavassa taulukossa on kaikki OpenGL:n geometriset alkiot:
glBegin-vakio | Tarkoitus | Huomautuksia |
---|---|---|
GL_POINTS | pisteitä | Käsky glPointSize(GLfloat) muuttaa pisteen lävistäjän kokoa; oletus on yksi pikseli. |
GL_LINES | viivoja | Viivat ovat erillisiä, ei toisissaan kiinni. Käsky glLineWidth(GLfloat) muuttaa viivan leveyttä pikseleinä. |
GL_TRIANGLES | kolmioita | |
GL_QUADS | nelikulmioita | Nelikulmio ei saa olla kovera, ja sen nurkkapisteiden tulee olla samalla tasolla. |
GL_POLYGON | yksi monikulmio | Monikulmio loppuu käskyyn glEnd(). Monikulmio ei saa olla kovera, ja sen nurkkapisteiden tulee olla samalla tasolla. |
Lisäksi on muutama ylimääräinen primitiivi, joita käytetään tehokkuussyistä: mitä vähemmän nurkkapisteitä on määriteltävä, sitä nopeampi ohjelma.
glBegin-vakio | Tarkoitus | Huomautuksia |
---|---|---|
GL_LINE_STRIP | viivanauha | Alkupisteen jälkeen jokainen uusi piste luo uuden viivan edellisestä. |
GL_LINE_LOOP | viivasilmukka | Kuin viivanauha, mutta lisäksi glEnd() yhdistää ensimmäisen ja viimeisen pisteen viivalla. |
GL_TRIANGLE_STRIP | kolmionauha | Kahden alkupisteen jälkeen jokainen uusi piste luo uuden kolmion kahden edellisen perusteella. |
GL_TRIANGLE_FAN | kolmioviuhka | Ensimmäinen piste on keskipiste. Toisen pisteen määrittelemän alkupisteen jälkeen jokainen uusi piste luo uuden kolmion edellisen pisteen ja keskipisteen välille. |
GL_QUAD_STRIP | nelikulmionauha | Kahden alkupisteen jälkeen jokaiset kaksi pistettä luovat uuden nelikulmion kahden edellisen perusteella. |
Nurkkapisteiden määrittely
muokkaaKaikki piirtotilassa sallitut komennot asettavat nurkkapisteisiin liittyvää tietoa. Sallittuja komentoja ovat glVertex, glColor, glIndex, glNormal, glTexCoord, glEvalCoord, glEvalPoint, glArrayElement, glMaterial ja glEdgeFlag.
Nurkkapisteiden sijainnit määritellään peräkkäisillä glVertex-komennoilla. Kaksiulotteinen piste tulkitaan kolmiulotteiseksi, jonka z-koordinaatti on 0. Voidaan ajatella, että määrittelyn yhteydessä nurkkapiste muunnetaan sen hetkisillä matriiseilla; matriiseista kerrotaan lisää myöhemmin.
/* viiva vasemmasta alakulmasta oikeaan yläkulmaan */ glBegin(GL_LINES); glVertex2f(-1.0, -1.0); glVertex2f(1.0, 1.0); glEnd();
Nurkkapisteeseen voidaan liittää muutakin tietoa, kuten väri. Komento glColor vaihtaa nykyisen värin. Kolmelle liukuluvulle tarkoitettu muoto ottaa parametreina RGB-väriarvot. Ne rajoitetaan automaattisesti välille [0, 1]. Komennosta on myös kuormitus kolmelle etumerkittömälle tavulle, jolloin arvot annetaankin välillä [0, 255].
Väri todellakin voidaan määritellä jokaiselle nurkkapisteelle erikseen. Tällöin esimerkiksi kolmio saa kauniin liukuvärjäyksen.
glBegin(GL_LINES); glColor3f(1.0, 0.0, 1.0); /* magenta */ glVertex2f(-1.0, -1.0); glVertex2f(1.0, 1.0); glColor3f(0.0, 0.0, 1.0); /* sininen */ glVertex2f(-1.0, 1.0); glColor3f(0.0, 1.0, 0.0); /* vihreä */ glVertex2f(1.0, -1.0); glEnd();
Kuvanmuodostusliukuhihna
muokkaaOpenGL:ää voi kuvata tehtaana, joka syö geometrisiä alkioita sekä rasterikuvia ja laittaa ne liukuhihnalle, joka loppujen lopuksi valmistaa niistä uusia rasterikuvia esimerkiksi kuvaruudulle.
(kaavio kuvanmuodostusliukuhihnasta)
Huomautuksia
muokkaa- Geometristen muotojen lisäksi OpenGL osaa piirtää rasterikuvia, mutta käytännössä kaksiulotteiseenkin grafiikkaan käytetään pintakuvioituja nelikulmioita.
- Max Paynen kolmiot ovat pieniä, varjostettuja ja saattavat käyttää useitakin pintakuvioita.
- Max Paynen OpenGL-piirtotila vaikutti nopeammalta kuin DirectX ainakin minun koneellani!