A fejlesztői blogban mostantól a grafikus szoftverfejlesztésről is olvashattok. Mivel a bada az OpenGL ES szabványt használja, célszerű az ismerkedést az OpenGL-lel kezdeni.
Mi is az az OpenGL?
Az OpenGL egy szabványos szoftveres interfész a grafikus hardverhez. Ez azt jelenti, hogy olyan utasításkészlet van benne definiálva, amely segítségével "működésre bírhatjuk" a videokártyát. A játékok grafikája egyre komplexebb, ez a tendencia megállíthatatlannak tűnik, a képernyőn megjelenő objektumok is egyre összetettebbek és nagyobb számítási teljesítményt igényelnek. Ezért célszerű ezekkel a számításokkal a GPU-t terhelni a processzor helyett: az OpenGL ehhez biztosít egy API-t (Application Program Interface), mely segítségével kihasználhatjuk a videokártyánkban szunnyadó erőt. Ez egy szabvány, minden videokártyával használható, így a kódunk ugyanúgy lefut egy ATI, egy nVidia, vagy egy más grafikus processzorral rendelkező kártyán is. Vagy épp a Samsung Wave-en.
Hogyan kezdődött az egész?
A számítógép megjelenése óta létezik igény a számítógépes játékokra és egyéb grafikus alkalmazásokra, melyek a hardverek fejlődésével és méginkább a videókártyák széleskörű elterjedésével egyre jobban néznek ki. Viszont ezekre fejleszteni régebben nem volt éppen leányálom: a 90-es évek elején már rengeteg eltérő típusú GPU volt a piacon, melyek azonban nem voltak szabványosítva. Ez azt jelentette, hogy mindegyikre más és más módszerrel kellett fejleszteni, a programozóknak ez rengeteg plusz munkát jelentett (mindegyikre saját driver és interfész írása). Ekkor lett igény egy szabványos grafikus könyvtárra. Ekkoriban a Silicon Graphics volt a legnagyobb gyártó, így a szabványuk, az IRIS GL vált a legelterjedtebbé, a nagy probléma azonban a nyílt forráskód hiányában rejlett. A rivális gyártók (Sun, IBM, HP) is kijöttek a saját interfészükkel, amely a PHIGS névre hallgatott, de nyíltsága ellenére vakvágánynak bizonyult a nehézkes használat és az elavult funkcionalitás miatt. A Silicon Graphics üzleti megfontolásból nyílt szabvánnyá akarta tenni az IRIS-t, azonban ez különböző buktatók miatt nem valósulhatott meg, így 1992 januárjában megszületett az OpenGL 1.0. Ez szabványosította a grafikus hardver elérését, miközben a "kód lefordítását a videokártya nyelvére" részt a gyártókra bízta, akik a videókártyák meghajtóiban (drivereiben) implementálták az OpenGL standard-et. Mondanom sem kell, ennek a hatása meglátszott a játékfejlesztésen is: a programozóknak nem kellett a sokfajta videokártyával külön-külön foglalkozniuk, ami rengeteg időt takarított meg nekik. A szabvány a kezdetek kezdetén az IRIS GL finomítása volt, később azonban a fejlődés hatására teljesen átírták. Pár évre rá megalakult az OpenGL Architectural Review Board, amely a szabvány fejlesztését tűzte ki célul. Azóta több "upgrade" is napvilágot látott, jelenleg a 4.0-ás verziónál tartunk, ez idén márciusban jelent meg. A verziók természetesen visszafele kompatibilisak, egy 4.0-t támogató kártya simán megbirkózik az alsóbb verziókkal is.
Teáskanna, az epikus objektum: egy paranccsal ki lehet rajzolni
Érdekesség: a nagy grafikus szabványőrületet a Microsoft sem tudta figyelem nélkül hagyni (különben lőttek volna a világuralomról szóló terveiknek), így megalkották a sajátjukat, a Direct3D-t és a DirectX-et, amely az OpenGL vetélytársává nőtte ki magát, jelenleg a 11. verziónál tart, azonban csak Windows alatt használható, míg az OpenGL Windowson, Linuxon és OS X-en is, sőt a PlayStation 3-ban is megjelent.
És ami számunkra fontos: megjelent az OpenGL ES, ami beágyazott rendszerekre "portolja át" az OpenGL-t. Beágyazott rendszereken azokat a készülékeket értjük, amelyek kevésbé rugalmasak, csak bizonyos feladatokat képesek ellátni, például a PDA-k, MP3 lejátszók, játékkonzolok és a mobiltelefonok. A szabványt a Khronos Group tartja karban, erről bővebben olvashattok majd a következő posztban.
A motorháztető alatt
Mivel a következőkben konkrét fejlesztési feladatokkal fogunk foglalkozni, muszáj tisztába jönnünk az alapfogalmakkal és a belső működéssel. Ezek következnek, a teljesség igénye nélkül.
A grafikus hardver működésébe nem szeretnék nagyon mélyen belemenni, a titok elsősorban a pipeline-os felépítésben rejlik. Ezt úgy lehet a legegyszerűbben elképzelni, mint egy gyártósort, amin egy pixel megy végig, és a sor minden "állomásán" valamilyen művelet hatására finomodik a kiindulási színe. Ennek nagy előnye a párhuzamosíthatóság, egy GPU több pipeline-t tartalmaz, ergo egyszerre több pixel színén dolgozik. Szerencsére ez el van fedve programozók elől. (Zárójelben tesszük hozzá, hogy a Prohardveren rengeteg cikket lehet olvasni a témában, itt most nem célunk azoknak konkurenciát állítani, ezért az egyszerűsített leírás.)
Az OpenGL alacsony szintű API, az objektumok felépítését úgynevezett primitívekből kell megoldanunk. Ilyenek a pont (vertex), a háromszög és a poligon (legalább három csúcsot tartalmazó sokszög), ezen kívül még fényforrásokat és egy kamerát is használhatunk. Az ezekből felépített objektumhalmazt jelenetnek (scene) nevezik. Összetettebb 3D-s tárgyakat tesszellálással állíthatunk elő, ami azt jelenti, hogy az objektumot háromszög-, illetve poligonhálóval közelítjük. Ha megfelelő mennyiségű primitívet használunk, szabad szemmel nem lehet észrevenni speciális felépítés adta "hibákat" - OpenGL-ben például egy gömböt is háromszögekből lehet kirakni, a "hibák" alatt az ebből fakadó dolgokra kell gondolnunk. A primitívekből álló háló felépítése általában az objektum matematikai modelljén alapul, ritkább esetben az egyes pontok koordinátáit kell megadni. Léteznek előre megírt függvénykönyvtárak, melyek nagyban leegyszerűsíthetik a fejlesztést, legelterjedtebb talán a GLUT, azaz az OpenGL Utility Toolkit. Ez tartalmaz magasabb szintű beépített metódusokat, így komplexebb objektumokat és effekteket is használhatunk azok implementálása nélkül.
Gömb tesszelláció ikozaéderből kiindulva
Egy OpenGL-ben felépített jelenet egyik legfontosabb eleme a kamera, azaz a nézőpont, ahonnan szemléljük az eseményeket. A 3D-ben felépített jelenet a kamerabeállításoknak megfelelően képződik le a 2D-s képernyőre. Ezt legegyszerűbben egy vektorként képzelhetjük el. Ha például szeretnénk 360°-ban körbenézni a jelenetünk körül, elég a kamerát körbemozgatni a középpont körül.
Lehetőségünk van az objektumainkat módosítani is, például eltolni, kicsinyíteni és nagyítani, forgatni. Mi történik a háttérben? A koordinátákat egy 4 x 4-es mátrix (4 oszlopot és sort tartalmazó táblázat) kezel. Affin transzformációkkal operálunk, melyekek olyan műveletek, amelyekben az új koordinátákat a régiekből lineáris függvényekkel állítjuk elő. Szemléletesen, a párhuzamos egyenesek módosítás után is párhuzamosak maradnak. Ezeket matematikailag nagyon egyszerűen lehet kezelni, egy mátrix-szorzással és egy eltolással megadhatók, ezért az OpenGL a transzformálásra és a modellünk 2D-be való leképezésére (modellview és projection) is ilyen mátrixokat használ. Nekünk, programozóknak szerencsére nem kell hozzányúlnunk a mátrixok tartalmához, ezeket is elfedi előlünk a keretrendszer.
Ezzel nagyjából le is fedtük az elméleti alapokat. Aki bővebben érdeklődik a téma iránt, a Red Book nevű, interneten is elérhető könyvet javaslom, kezdőként nagyon sok hasznos információt tartalmaz.