Juha-Pekka Jokela | jpjokela@surfeu.fi
Tinygl-kurssi, osa 3

Tinygl on MorphOS:n opengl-yhteensopiva 3D-rajapinta, joka löytyy MorphOS:n versiosta 1.4 tai sitä uudemmista. Kurssi sopii kaikille, jotka ovat kiinnostuneita opengl-ohjelmoinnista. Kurssin osat 1 ja 2 käsiteltiin Sakussa #47 (1/2005).

Uudet asiat: Display listit, valaistus, face culling

Display list
Display list sisältää joukon opengl-kutsuja, jotka suoritetaan järjestyksessä listaa kutsuttaessa. Display list voi sisältää myös kutsuja muihin listoihin. Jos jokin kappale vaatii laskemista, mutta se ei muutu ohjelman suorituksen aikana, kannattaa se "laskea suoraan display listiin". Tällöin laskut lasketaan ohjelman suorituksen aikana vain kerran. Siirtyminen käyttämään display listejä vaatii ylensä vain erittäin pieniä muutoksia koodiin (vertaa osa 2:n ja osa 3:n koodeja) ennen glCallList():iä suoritetut funktiot (translaatiot, pyöritykset, skaalaukset, värin vaihto ym.) voivat vaikuttaa siihen, mihin/miten listan sisältö piirretään.

opengl:llä voi piirtää primitivejä kolmella eri tavalla:
1) Suoraan käskyillä
2) Display Listeillä
3) Vertex Arraylla

Periaatteessa ensimmäinen vaihtoehto on hitain ja viimeinen nopein. Tosin jos esim. piirrettävä data muuttuu jatkuvasti, ei ole ehkä järkevää käyttää display listejä tai vertex arrayta.

Face culling
Jos face culling on käytössä, piirretään polygoneista vain yksi puoli (eli esimerkiksi kuution sivu piirretään vain silloin, jos se on kameraan päin)

Tapa jolla polygonin etupuoli määräytyy voidaan valita funktiolla glFrontFace(). GL_CW määrittää, että polygonin etupuoli piirretään myötäpäivään, GL_CCW taas vastapäivään. Perusasetus on GL_CCW. Jotta homma saataisiin vielä sekavammaksi, voidaan myös erikseen valita se, kumpi sivu piirretään. Tämä onnistuu funktiolla glCullFace(), mahdollisina argumentteina tietenkin GL_FRONT ja GL_BACK.

Normaalit
Sivun normaali on suora (normaalisti yksikkövektori), joka on kohtisuorassa sivua vasten. Normaaleja käytetään valaistuksen laskemisessa. Normaali määritetään funktiolla glNormal3f().

Normaali voidaan määrittää erikseen joka tasolle tai joka vertexille. Normaalit täytyy määrittää joka vertexille erikseen, jos halutaan käyttää smooth shadingia (glShadeModel(GL_SMOOTH)). Ylensä vertex-kohtaiset normaalit voidaan laskea siten, että otetaan keskiarvo kaikkien niiden sivujen normaaleista, jotka jakavat saman vertexin. Tämä tapa on hyvä varsinkin silloin, jos data on "ennalta tuntematon". Esimerkkikoodissa kuusen yläosan vertexit on laskettu "suunnilleen", tarkkuudessa olisi parantamisen varaa.

Huom! Normaali määrittää suunnan (yksikkövektori), ei normaalin päätepistettä!

Valaistus
Valaistus riippuu useista eri tekijöistä ja niiden keskinäisistä suhteista, kuten:
- Valonlähteen tyyppi ja sijainti
- 3D-mallien sijainti
- 3D-mallien materiaaliasetukset
- "Kameran" sijainti

Valaistuksen tyyppiä voidaan muuttaa funktiolla glLightfv(). Argumentteina annetaan muutettavan valon numero, mitä muutetaan ja uudet arvot. Eli siis esimerkiksi glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient) (kts. esimerkkikoodi).

Ambient: Valokomponentti, joka tulee joka suunnasta yhtä voimakkaana. Minimiarvo pimeimmille kohdille. Pelkällä ambient-valaistuksella kuva näyttää samalta kuin ilman valaistusta.

Diffuse: Valokomponentti, jonka määrä riippuu tason kulmasta suhteessa valonlähteeseen. Saa 3D-grafiikan näyttämään kolmiulotteiselta.

Specular: Valokomponentti, joka määrittää, millä tavalla pinta heijastaa valoa. Riippuu vahvasti materiaalin asetuksista.

Kuvan vasemmassa reunassa Ambient on maksimiarvossaan, oikeassa reunassa taas Diffuse (muut arvot ovat nollassa).

Esimerkkikoodi
Makefile osalle kolme

Sivun alkuun