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:

  1. OpenGL-ikkunan (ja mahdollisten muidenkin näyttömuistipuskurien) tyhjennys
  2. piirtäminen
  3. piirtokäskyjen näyttäminen kuvaruudulle

Ensimmäinen ja viimeinen ovat yksinkertaisia perustoimintoja. Piirtäminen on huomattavasti monipuolisempaa.

Puskureiden tyhjennystä muokkaa

Tarkastellaan 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 muokkaa

Komento 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 muokkaa

Seuraavassa 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 muokkaa

Kaikki 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 muokkaa

OpenGL:ää 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!