Előadást letölteni
Az előadás letöltése folymat van. Kérjük, várjon
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)
Hasonló előadás
© 2024 SlidePlayer.hu Inc.
All rights reserved.