Az előadás letöltése folymat van. Kérjük, várjon

Az előadás letöltése folymat van. Kérjük, várjon

Számítógépes Grafika OpenGL és SDL alapok

Hasonló előadás


Az előadások a következő témára: "Számítógépes Grafika OpenGL és SDL alapok"— Előadás másolata:

1 Számítógépes Grafika OpenGL és SDL alapok

2 Órai programok A félév során vett programok elérhetőek a oldalról Mindegyik Visual Studio-s program alapbeállítás szerint a T:\ meghajtó gyökerében keresi az OGLPack-ot Ez egy egyszerű zip fájl, ami minden, OpenGL-es program futtatásához szükséges library-t tartalmaz Innen érhető el:

3 OGLPack Tartalmazza a következőket használó programok Windows alatti fordításához és futtatásához szükséges fájlokat: Glew: GLM: SDL: SDL Image:

4 OGLPack Az óra kódok használatához már csak egy T:\ meghajtóra van szükség, aminek a gyökerében az OGLPack könyvtár van: subst t: .

5 Első SDL-es program

6 SDL Az SDL (Simple DirectMedia Layer - ) könyvtár egy crossplatform multimédiás könyvtár ami alacsony szintű hozzáférést ad Audio Bemeneti (egér, billentyűzet, joystick) Grafikus (OpenGL-en keresztül GPU-hoz pl.) eszközökhöz

7 SDL Mi alap ablakozási dolgokra fogjuk használni (ablakok létrehozása, események kezelése) Illetve magát az OpenGL context-et is rajta keresztül hozzuk létre ...elfedve, hogy pontosan hogyan is kell ezt Windows alatt ...vagy Linux/OSX/akármi alatt

8 SDL Több almodulból áll
Az SDL inicializálásakor meg kell adni, hogy milyen almodulokat akarunk még használni Mi általában csak SDL_Init( SDL_INIT_VIDEO ); hívást használunk

9 SDL erőforrások Az SDL-ben az erőforrásokat üres struktúrákra mutató pointerekkel azonosítják Tehát SDL_Window* egy ablakot azonosít De maga az SDL_Window struct így néz ki: typedef struct SDL_Window SDL_Window; Továbbiakban nyugodtan gondoljatok ezekre úgy, mint sima egész számokra Ha egy erőforrás attribútumait kell lekérdezni, akkor arra külön függvényeket kell hívni

10 SDL rajzolás A rajzoláshoz szükséges erőforrásokat és állapotváltozókat egy úgynevezett Renderer kezeli A Renderer létrehozásához egy rajzterületre, ablakra van szükség A rajzolás állapot alapú A tényleges rajzparancsok eredménye az állapotváltozók aktuális értékeitől függenek Állapotváltozó például a rajzolási szín, a vonalvastagság stb.

11 SDL A gyakorlatokon az SDL 2.0-át fogjuk használni
A programhoz linkelendő lib-ek: SDL2.lib SDL2main.lib A használatához szükséges header: #include <SDL.h>

12 SDL A fordításhoz szükséges lib-eket meg kell adni a Visual Studio-nak
Erre két lehetőség van Kódból Project properties-ben

13 SDL libek megadása kódból
A következőket írjuk be az #include-ok után #pragma comment(lib, "SDL2.lib") #pragma comment(lib, "SDL2main.lib")

14 SDL libek megadása properties-ben

15 SDL futtathatók beállítása
A programunknak szükséges lesz arra, hogy lássa az SDL-es függvények implementációit Ezek különböző DLL fájlokban vannak A DLL-ek a OGLPack\bin mappán belül: \x86: 32 bites DLL-ek \x64: 64 bites DLL-ek A szükséges DLL-eket olyan helyre kell másolni, ahol a rendszer látja (PATH környezeti változó) Vagy amit már csináltunk:

16 SDL futtathatók beállítása

17 01_HelloSDL A program letölthető innen: p A program a következőket csinálja: Inicializálja az SDL-t Létrehoz egy ablakot Létrehoz egy Renderer-t, rajzolót, amit ablakhoz rendel Rajzol Megszünteti a Renderer-t Megszünteti az ablakot és leállítja az SDL-t

18 01_HelloSDL/main.cpp #include <SDL.h> #include <iostream>
void exitProgram() { std::cout << "Kilépéshez nyomj meg egy billentyűt..." << std::endl; std::cin.get(); } int main( int argc, char* args[] ) atexit( exitProgram ); ...

19 01_HelloSDL/main.cpp Az atexit() parancs a paraméterben kapott függvénypointer által mutatott függvényt hívja meg az alkalmazás terminálásakor Ez a függvény most az exitProgram, amit csak arra használunk, hogy a konzolablak eltűnése előtt megvárjunk egy billentyűleütést

20 01_HelloSDL/main.cpp // 1. lépés: inicializáljuk az SDL-t if ( SDL_Init( SDL_INIT_VIDEO ) == -1 ) { std::cout << "[SDL indítása]Hiba az SDL inicializálása közben: " << SDL_GetError() << std::endl; return 1; } // 2. lépés: hozzuk létre az ablakot, amire rajzolni fogunk SDL_Window *win = 0; win = SDL_CreateWindow( "Hello SDL!", 100, 100, 640,480,SDL_WINDOW_SHOWN); if (win == 0){ std::cout << "[Ablak létrehozás]Hiba az SDL inicializálása közben: " << SDL_GetError() << std::endl; return 1; }

21 SDL_INIT int SDL_Init(Uint32 flags):
Inicializálja a paraméterben kapott SDL alrendszereket Ha többet akarunk, akkor bináris VAGY művelettel kapcsoljuk össze őket Alrendszerek:

22 SDL_Window A következőképpen van deklarálva: typedef struct SDL_Window SDL_Window; Egy SDL-es ablak-azonosító Az ablak attribútumait ne a pointeren keresztül próbáld lekérni vagy módosítani! Erre külön függvények vannak (például SDL_SetWindowTitle és társai)

23 SDL_CreateWindow SDL_CreateWindow:
Létrehoz egy w széles, h magas ablakot a title fejléccel, az (x,y) képernyőkoordinátákon, flags megjelenítési attribútumokkal és siker esetén visszaadja az azonosítóját (különben NULL)

24 SDL_WindowFlags Megjelenítési tulajdonságok, szintén binárisan VAGY-olandóak

25 01_HelloSDL/main.cpp // 3. lépés: hozzunk létre egy renderelőt, rajzolót SDL_Renderer *ren = 0; ren = SDL_CreateRenderer( win, , SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); if (ren == 0) { std::cout << "[Renderer létrehozása]Hiba az SDL inicializálása közben: " << SDL_GetError() << std::endl; return 1; }

26 SDL_CreateRenderer SDL_CreateRenderer:
2D-s renderer context létrehozására használandó Azaz lényegében lehetővé teszi, hogy tudjunk rajzolni az ablakunkra Ha sikertelen a renderelő létrehozása, akkor NULL pointerrel tér vissza

27 SDL_CreateRenderer SDL_Renderer* SDL_CreateRenderer( SDL_Window* window, int index, Uint32 flags) Az ablak azonosítója, amire rajzolni szeretnénk a létrehozandó renderer segítségével

28 SDL_CreateRenderer SDL_Renderer* SDL_CreateRenderer( SDL_Window* window, int index, Uint32 flags) A renderer indexe, vagy -1, ha a kért képességeket (hardveresen gyorsított rajzolás stb., lásd flags) támogató első megfelel a céljainknak

29 SDL_CreateRenderer SDL_Renderer* SDL_CreateRenderer( SDL_Window* window, int index, Uint32 flags) Mi hardveresen gyorsítottat szeretnénk, a többi:

30 01_HelloSDL/main.cpp // 4. lépés: töröljük az ablak háttérszínét SDL_SetRenderDrawColor(ren, 0, 0, 0, 255); SDL_RenderClear(ren); // rajzoljunk egy vonalat más színnel (10,10)-ből (10,60)-ba SDL_SetRenderDrawColor(ren, 0, 255, 0, 255); SDL_RenderDrawLine( ren, 10, 10, 10, 60); // jelenítsük meg a backbuffer tartalmát SDL_RenderPresent(ren); // várjunk 2 másodpercet SDL_Delay(2000);

31 SDL_SetRenderDrawColor
SDL_SetRenderDrawColor( SDL_Renderer* renderer, Uint8 r, Uint 8 g, Uint8 b, Uint8 a): Beállítja a renderer színét az (r,g,b) színre, a átlátszósággal Minden egyes színkomponens és az átlátszóság erőssége közötti egész szám

32 SDL_RenderClear int SDL_RenderClear( SDL_Renderer* renderer):
Sikertelen törlés esetén negatív számmal tér vissza Az aktuális rajzolási színnel „törli” az ablak rajzterületét

33 SDL_RenderDrawLine int SDL_RenderDrawLine( SDL_Renderer* renderer, int x1, int y1, int x2, int y2): Ez is, mint a többi SDL rajzoló utasítás, negatív számmal tér vissza, ha sikertelen (ilyenkor a SDL_GetError()-ral kideríthető a hiba oka) Egyébként a renderer-rel (az ő ablakára) rajzol egy egyenes szakaszt, ami az (x1,y1) és (x2,y2) pontokat köti össze

34 SDL_RenderPresent void SDL_RenderPresent( SDL_Renderer* renderer):
Eddig minden rajzolást egy képernyőn kívüli memóriaterületre végeztünk Ezzel az utasítással jelezzük, hogy végeztünk a aktuális képkocka, frame kirajzolásával és most már ezt kell megjeleníteni

35 SDL_Delay void SDL_Delay(Uint32 ms):
A paraméterben megadott milliszekundomot várakozik a program futása

36 01_HelloSDL/main.cpp SDL_DestroyRenderer( ren ); SDL_DestroyWindow( win ); SDL_Quit(); return 0; }

37 OpenGL

38 OpenGL Kiforrott szabvány: 1992 óta van
Rengeteg elavult dolgot görgetett maga előtt OpenGL 3.0-nál ezeket megpróbáltál kidobni és újrarendezni az API-t Több-kevesebb sikerrel: Van egy úgynevezett Core profile, ami csak a modern OpenGL utasításait engedi használni De a régi kódok futtathatóságáért létezik egy Compatibility profile is, amiben minden függvény él, ami valaha OpenGL-es volt

39 OpenGL A félév során Core profile-lal fogunk foglalkozni
Általában sokkal kisebb az overhead az utasítások végrehajtásánál Cserébe a Core-ból kirakott utasítások csendben elhalnak (=hibajelzés nélkül nem csinálnak semmit)

40 OpenGL Aktuális verzió: sion/ Nagyon hasznos olvasmány: pdf és pdf Vigyázzatok: ez specifikációs, nem pedig implementációs dokumentáció

41 OpenGL pipeline Részletes pipeline map: truc.net/doc/OpenGL%204.4%20Pipeline%20Map .pdf

42 OpenGL pipeline (gyengébb idegzetűeknek)

43 OpenGL működése Általában egy ablakba szeretnénk rajzolni
A rajzolás egy OpenGL context-en keresztül történik, amihez hozzárendeljük az ablak megfelelő rajzterületét A kiadott OpenGL utasítások mindig az aktuális context-ben hajtódnak végre A rajzolás egy fix és programozható fázisokat is tartalmazó pipeline-on keresztül történik

44 OpenGL működése Az inkrementális képszintézis egyes lépéseinek pontos mikéntjeit programozható fázisok (shaderek) segítségével határozhatjuk meg Vannak cross-API kezdeményezések is shader- nyelvekre (NV CG) De mi az OpenGL natív magas szintű programnyelvét használjuk, a GLSL-t

45 Context Az aktuális OpenGL példány összes állapotát (állapotváltozóját) tárolja „Állapot(változó)” például egy tároló is, amiben pl. a kirajzoláshoz szükséges adatokat (VBO) vagy akár programot (shadert) tárolunk Egy (akár) képernyőre is kikerülő framebuffert is reprezentál (default framebuffer) Ha nincs explicit más FBO kötve, akkor minden rajzolási parancs eredménye ide megy OpenGL rajzolási parancs mindig az éppen aktív Context-en megy keresztül (erről később)

46 Adattípusok A C++-szal ellentétben az OpenGL pontosan megmondja, hogy hány biten és milyen reprezentációban várja a különböző számtípusokat Ezért van annyi GL* kezdetű típusnév typedef Figyeljünk ezekre

47 Adattípusok

48 Adattípusok

49 Erőforrások Az OpenGL az erőforrások azonosítására előjel nélküli egész számokat használ (Gluint) Létrehozásukra általában glGen* kezdetű utasítások szolgálnak Ezek visszaadnak (nem feltétlen return-nel) egy erőforrásazonosítót, ami a context névterébe kerül Alapból minden context-nek saját névtere van – de van lehetőség context-ek névtereit összekapcsolni (context sharing)

50 Erőforrások A nulla erőforrásazonosító mindig egy alapértelmezett értékre hivatkozik – ilyet erőforrás-létrehozó parancs nem adhat vissza (ha minden rendben van) Erőforrás-típusonként az azonosítók így 1-ről indulnak Kivéve, ha már létezett a névterünkben azonosító ebből a típusból; erről majd később a context sharing-nél

51 Erőforrás létrehozása
Név generálása („deklaráció”) Név aktívvá tétele (bind-olás) Erőforrás-műveletek elvégzése („definíció”) Névhez rendelt erőforrás deaktiválása (=a 0-s erőforrásazonosító aktívvá tétele)

52 Erőforrások kezelése Az erőforráskezelő eljárások is állapot-alapon működnek Azaz a kiadott parancs mindig a parancs által módosított típus éppen aktív példányára hat Vagyis azt módosítja, ami éppen bind-olva van Röviden, amikor egy már létező erőforrást módosítunk: Bind Művelet Unbind = bind(0)


Letölteni ppt "Számítógépes Grafika OpenGL és SDL alapok"

Hasonló előadás


Google Hirdetések