Előadást letölteni
Az előadás letöltése folymat van. Kérjük, várjon
KiadtaCsilla Fülöpné Megváltozta több, mint 8 éve
1
1 OpenGL grafikus rendszer Dr. Nehéz Károly egyetemi adjunktus Miskolci Egyetem Alkalmazott Informatikai Tanszék
2
2 Az OpenGL története ► Silicon Graphics, IrixGL (1980) ► 1990, OpenGL nyitott (nyílt) grafikus könyvtár ► GLX – összeköttetés az ablakozó rendszerrel ► GLU – gl utility standard kiegészítés ► GLUT – gl utility újabb kiegészítés ► ARB (Architechtural Review Board) konzorcium ► ARB tagok (Silicon Graphics, Microsoft, Sun, IBM, NVIDIA, ATI, Matrox)
3
3 OpenGL felépítése
4
4 Geometriai adatok rajzolásának alapjai ► A rajzolási terület törlése egy adott színnel ► Geometrikus primitívek rajzolása (pont, szakasz, poligon) ► A geometrikus primitívek tulajdonságainak megváltoztatása (szín, vonaltípus, vonalvastagság, stb.) ► Normálvektorok megadása ► Rajzolás befejezése
5
5 ► A megjelenített komplex geometria, minden esetben primitív grafikus elemekből áll. (legtöbbször háromszögek, négyszögek) A modern grafikus kártyák hardveresen támogatják ezek „renderelését” ► Alapvető rajzolási operációk: Képernyőtörlés (a színbuffer törlése) Geometriai objektum kirajzolása. (közvetlen vagy tárolt formában) Raszter objektum kirajzolása. (raszter objektum lehet: bitmap, karakter fontkészlet elem)
6
6 Ablak törlése ► Az aktuális video-memória minden esetben vagy memória-szemetet, vagy valamilyen előző kirajzolt fázis képét tartalmazza. Ezért kell feltölteni a színbuffert háttérszínnel. Miért nem töltjük fel a buffer egy nagyméretű háttérszínre festett négyzettel? 1. A video memória nagyon nagy méretű. Pl.: 1024*768 - 24 bites kép esetén 2.3 Mbyte adat törlése szükséges minden képfázis rajzolása előtt. 2. A raszterizálás folyamán több transzformációt végez a rendszer, így sokszor nehéz kiszámolni a megfelelő méretű téglalapot. 3. A ‘takart felületek eltávolítása’ miatt a négyzet térbeli helyzete is nehezen lenne meghatározható 4. A grafikus rendszer több buffert is tartalmaz, amit ugyancsak törölni kellene minden új fázis rajzolása előtt. (stencil, accumlation, depth bufferek) Megoldás: speciális függvényhívások alkalmazása
7
7 Ablak törlése ► Példa: ablak hátterének feketére festése glClearColor (0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BITS); Az első függvényhívás feketére állítja a törlés színét. (Red Green Blue Alpha formátumban) A törlés színét elég egyszer beállítani, mivel a rendszer egy állapotváltozóban tárolja a hatékonyság növelése érdekében
8
8 Ablak törlése ► Példa: glClearColor (0.0, 0.0, 0.0, 0.0); glClearDepth(0.0); glClear(GL_COLOR_BUFFER_BITS | GL_DEPTH_BUFFER_BIT); ► A mélységbuffer alapértelmezett értéke 0.0 Az OpenGL lehetővé tesz több buffer egyidejű törlését a sebesség növelése érdekében.
9
9 Színek megadása ► A OpenGL rendszerben a geometriai és a színinformáció egymástól független. ► Általában a programozó megad valamilyen színinformációt majd ezt követően adja meg a grafikus adatokat. Aktuális_Szín(piros); Rajzol(objectA); Rajzol(objectB); Aktuális_Szín(zöld); // mi lesz zöld? Aktuális_Szín(kék); Rajzol(objectC); // milyen színű lesz objectC?
10
10 Színek megadása ► A színek megadásának módja: glColorXY() glColor3f(1.0, 0.0, 0.0); // piros glColor3f(0.0, 1.0, 0.0); // zöld glColor3f(0.0, 0.0, 1.0); // kék glColor3f(1.0, 1.0, 1.0); // fehér glColor3f(0.0, 0.0, 0.0); // fekete glColor3f(0.5, 0.5, 0.5); // szürke árnyalat
11
11 Rajzolás befejezése ► Modern grafikus hardverek grafikus csővezeték elvén működnek. A CPU végrehajt egy grafikus utasítást, de e mellett egy másik egység transzformál, vág, árnyal, texturát tömörít, stb. Majd az eredmény megjelenik a különböző bufferekben. Ameddig egy pont (vertex) megjelenik a csővezeték bementénél, addig a transzformációs hardver még az előző elküldött elemen dolgozik. ► Az alkalmazás futhat elosztott környezetben is, több gépen. A kliens gyűjti a hálózatról a soron következő parancsokat. Jó volna tudni, hogy mikor mondhatjuk azt, hogy a képfázis készen van? ► Az OpenGL nem tárolja a grafikus primitíveket, hanem az előzetes beállításoknak megfelelően az állapotgép utasításait hajtja végre a soron következő grafikus elemen!
12
12 Rajzolás befejezése ► Megoldás: glFlush() A glFlush() minden képfázis végét jelezve végre kell hajtani. ► glFinish() a különbség csak annyi, hogy a hívás után várakozik a befejezésre. szinkronizáció esetén user-input esetén biztosítja a teljes rajz megjelenését
13
13 Takart felületek kezelése ► A több objektumot tartalmazó kép esetén a kirajzolás sorrendjétől függetlenül kell biztosítani, hogy a takart felületek ne látszanak. Pl: while(1) { getNézőpont_egérpozíció_alapján(); glClear(GL_CLEAR_COLOR_BUFFER_BIT); Rajzol(3dobjectA); Rajzol(3dObjectB); } ► Olyan módszert kellene alkalmazni, amely minden esetben, nézőponttól függetlenül jól működik.
14
14 Megoldás: z-buffer algoritmus alkalmazása: A z-buffer algoritmus a takarási feladatot az egyes pixelekre oldja meg, oly módon, hogy minden pixelre megkeresi azt a poligont, amelynek a pixeleken keresztül látható pontjának a z koordinátája minimális. 1. Ezt a keresést azzal támogatja, hogy minden pixelhez letárol egy aktuális mélység értéket. 2. A poligonokat egyenként dolgozza fel és meghatározza a poligonok vetületén belül eső pixeleket. 3. Inicializáláskor a z-buffer minden pixelében a tárolható legnagyobb érték van (‘végtelennel’ történő inicializálás). 4. A rajzolási folyamat során a poligonok vetületi képe jelenik meg a szín bufferben, de ugyanakkor pixelenkénti z- koordinátákat a z-buffer tárolja. Ha p(i,j) pixelhez letárolt z koordináta kisebb, mint az aktuális poligon p(i,j) pixelre eső z- koordinátája, akkor felülírjuk a letárolt z-koordinátát, mivel ez azt jelenti, hogy az aktuális poligon ezen p(i,j) pixele nincs takarásban (közelebb esik a képernyő síkjához, mint a letárolt érték). Amennyiben z-buffer felülírás történik, akkor természetesen a képernyő megfelelő pixelének színe is módosul.
15
15 A z-buffer algoritmus OpenGL megvalósítása ► glEnable(GL_DEPTH_TEST); … … while(1) { glClear (GL_CLEAR_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); getNézőpont_egérpozíció_alapján(); Rajzol(3dobjectA); Rajzol(3dObjectB); }
16
16 Pontok, szakaszok, poligonok leírása ► Minden geometriai primitív végső soron leírható vertex koordináták segítségével. ► Pontok – vertexek sorozata, ► Szakaszok – kezdő és végpont vertex koordinátáival ► Poligonok – csúcspontok vertex koordinátáival ► Mi a pont, szakasz, poligon? Matematikai értelemben egyszerű fogalmak ‘OpenGl értelemben’ más a helyzet, mert a a primitíveket lebegőpontos formában adhatjuk meg, limitált pontossággal. Az OpenGL színbuffere egy bittérkép, aminek alapegysége a képpont. Sok esetben előfordul, hogy a különböző lebegőpontos értékekkel megadott pontok ugyanarra a pixelre esnek.
17
17 ► Pontok: pontokat 2 vagy 3 koordináta segítségével adhatunk meg. Minden transzformációs lépés 3 dimenzióban történik. Ha csak két koordinátát adunk meg akkor a harmadikat automatikusan zérónak tekinti a rendszer. Az OpenGL értelmezi az úgynevezett a háromdimenziós projektív geometria homogén koordinátáit. Ekkor egy pontot 4 koordináta ír le: (x,y,z,w). Ha a w != 1.0 akkor a rendszer (x/w, y/w, z/w) pontot jeleníti meg.
18
18 ► Szakaszok,vonalak: az OpenGL vonal, vonalszakaszt jelent. Nem a matematikai értelemben vett egyenest. Egymással kapcsolódó szakaszok esetén elegendő a végpontokat megadni.
19
19 ► Poligonok: zárt vonalszakaszok halmaza. A szakaszok nem metszhetik egymást. A poligonoknak konvexeknek kell lenniük. Nem tartalmazhatnak kivágásokat. ► A poligonok rajzolása nem hatékony, célszerűbb háromszögekkel dolgozni. Amennyiben konkáv vagy kivágott poligonokkal szeretnénk dolgozni, akkor segítségünkre lehet a GLU által támogatott tessallációs függvények.
20
20 Speciális tulajdonságok ► A poligonok pontjainak nem szükségszerűn kell egy síkon lenniük.
21
21 Görbék ► A görbék interpolációja vonalszakaszokkal történik. Minél több a vonalszakaszok száma, annál finomabb a görbe, de a rajzolás sebessége csökkenhet.
22
22 Vertexek megadása ► Minden geometriai objektum vertexek rendezett halmazával írható le. ► glVertex*() függvény segítségével glVertex2s(4,5); glVertex3d(0.0, 0.0, 4.54342233); glVertex4f(0.0, 1.2, 3.4, 1.0); float dvect[3] = {1.0f,1.0f,3.0f}; glVertex3dv(dvect);
23
23 Geometriai primitívek megadása ► glBegin(GL_POLYGON); glVertex2f(0.0, 0.0); glVertex2f(0.0, 3.0); glVertex2f(3.0, 3.0); glVertex2f(4.0, 1.5); glVertex2f(3.0, 0.0); glEnd(); ► glBegin() adja meg a geometriai primitív típusát ► Ugyanaz a vertex halmaz, különböző primitívként is megjeleníthető. Mi történik ha egy poligon esetén csak 1 vertexet adok meg? Mi történik ha a glVertex hívások között más függvényhívásokat is szerepeltetünk?
24
24
25
25 OpenGL - Hello háromszög #include void kirajzol(void); void main() { glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);// megjelenítési mód glutInitWindowSize (500, 500);// ablakméret glutCreateWindow ("Elso OpenGL pelda - 'Hello háromszög'");// ablak létrehozása glutDisplayFunc (kirajzol);// a rajzoló függvény megadása glutMainLoop ();// végtelen ciklus a rajzoláshoz } void kirajzol(void) { glClearColor (0.5f, 0.5f, 0.5f, 0.0f);// szürke szín glClear (GL_COLOR_BUFFER_BIT);// képernyőtörlés glBegin (GL_TRIANGLES);// háromszögeket rajzolunk glVertex2f(0, 0); glVertex2f(0.5, 0.5); glVertex2f(0.5, 0.0); glEnd ();// vége glFlush ();// rajzold ki (de) azonnal! }
26
26 Megkötések a glBegin() és glEnd() párok használatában ► glBegin() és glEnd() pár között lehetőség van: a színek megváltoztatására, normál vektorok, textura-koordináták, anyagtulajdonságok, megadására. ► Lehetőség van bármilyen más ‘nem grafikus’ művelet elvégzésére glVertex*() vertex koordináták glColor*() vertex színek glIndex*()color-index glNormal*() normál vektorok glEvalCoord*() koordináta generálás glCallList() display listák glTextCoord*() Textura koordináták glEdgeFlag*()élek glMaterial*()anyagtulajdonságok
27
27 Példa: Kör rajzolása #define PI 3.1415192535897 int points = 100; glBegin(GL_LINE_LOOP); for (int i = 0; i < points; i++) { float szog = 2 * PI * i / points; glVertex2f(cos(szog), sin(szog)); }glEnd(); Önálló feladat: az első példa (hello háromszög) módosítása a fenti kódrészlet segítségével.
28
28 Pontok, szakaszok, poligonok megjelenítési tulajdonságai ► A programozást az állapotgép számos előre beállított ‘default’ értékei segíti. Pl: pont – egy pixel a képernyőn szakasz – egy pixel széles szakasz poligon – egy adott színnel befestett terület ► Pontok esetén a méret: glPointSize(GLfloat size) – hívással módosítható
29
29 ► A pont maximális mérete a glGetFloatv(GL_POINT_SIZE_RANGE, …); segítségével lekérdezhető. ► Ha az antialiasing (csipkézettség mentesítés) kikapcsolt állapotban van, akkor a megadott pontméret egészre kerekített pixelértéket jelent. Ellenkező esetben egy körkörös pontcsoport lesz kirajzolva, amelynek határpixelei halványabb színnel lesznek kirajzolva.
30
30 Szakaszok tulajdonságai ► Vonalvastagság és vonaltípus az állítható tulajdonságok. glLineWidth(GLfloat width); //alapértlemezett:1.0 A vonalvastagság pixelekeben mért értéke csak a csipkézettség mentesítés kikapcsolása esetén jelent egész számú pixelértéket. 1,2,3 – 1,2,3. ► A szakasz maximális szélessége a glGetFloatv(GL_LINE_WIDTH_RANGE, …); segítségével kérdezhető le.
31
31 Vonaltípusok ► glLineStipple(1, 0x3F07); // faktor, bitek glEnable(GL_LINE_STIPPLE); // bekapcsolás ► 0x3F7 – 0011111100000111 3 pixel be, 5 ki, 6 be, 2 ki. ► Ha a faktor pl. 2 akkor, 6 pixel be, 10 ki, 12 be, 4 ki. ► glDisable(GL_LINE_STIPPLE); ► Default esetben: glLineStipple(1, 0xFFFF);
32
32 Minta Faktor (szorzó) 0x00FF1 ---- ---- ---- ---- - 0x00FF2 0x0C0F1 --- -- --- ---- 0xAAAA1 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 0xAAAA2 0xAAAA3 0xAAAA4
33
33 Szakaszok példaprogram
34
34 Poligonok tulajdonságai ► Minden poligon kétoldalas, egymástól független tulajdonságokkal rajzolható. ► glPolygonMode(GLenum face, GLenum mode); face: GL_FRONT_AND_BACK GL_FRONT, GL_BACK mode: GL_POINT, GL_FILL, GL_LINE
35
35 ‘Front facing’ - poligon ► Az óramutató járásával ellentétes sorrendű vertexek (GL_CCW) reprezentálják az elülső (front) lapot. ► glFrontFace(GLenum mode) mode: GL_CCW, CL_CW
36
36 Sebesség növelése ► A nemlátható „hátsó” élek eltüntetése (back-culling): glBegin(GL_CULL_FACE); glCullFace(GLenum mode); mode: GL_FRONT, GL_BACK Az vertexek ablak koordinátái alapján a rendszer el tudja dönteni, hogy melyik oldalt kell kirajzolni: Példa: ha GL_CCW módban vagyunk és a>0 akkor a front oldalt látjuk. Ha a<0 akkor a hátsó oldalt látjuk.
37
37 Szinusz görbe rajzolás
38
38 Egy lehetséges megoldás #include #define PI 3.1415192535897 void kirajzol(void); void main() { glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);// megjelenítési mód glutInitWindowSize(500,500);// ablakméret glutCreateWindow("Szinusz görbe rajzolása");// ablak létrehozása glutDisplayFunc(kirajzol);// a rajzoló fuggvény megadása glutMainLoop();// végtelen ciklus a rajzoláshoz } void rajzolkoordinata() { glBegin(GL_LINES);// Egyenesek rajzolása glVertex2f(-2,0); glVertex2f(2,0); glVertex2f(0,1); glVertex2f(0,-1); glEnd(); }
39
39 Egy lehetséges megoldás. (folyt.) void kirajzol(void) { glClearColor(0.5f,0.5f,0.5f,0.0f);// szürke szin glClear(GL_COLOR_BUFFER_BIT);// képernyőtörlés // // koordináta rendszer rajzolása // glLineWidth(2.0); glColor3f(1.0f,0.0f,0.0f); rajzolkoordinata(); // // beosztás kirajzolása // glLineWidth(12.0); glEnable (GL_LINE_STIPPLE); glLineStipple (3, 0x0101); // szaggatott rajzolkoordinata(); glDisable (GL_LINE_STIPPLE); // // a szinusz görbe // glLineWidth(3.0); glBegin(GL_LINE_STRIP);// Egyenesek rajzolása glColor3f(1.0f, 1.0f, 1.0f); for (float i = -2.0f * PI; i < 2.0f * PI; i += 0.1)// sinus görbe -2PI tol 2PI közötti intervallumban { glVertex2f(i/PI, sin(i)); } glEnd(); glFlush();// rajzold ki }
40
40 OpenGL adattípusok OpenGL adattípus Belső reprezentáció C típus C suffix GLbyte 8-bit integer Signed char b GLshort 16-bit integer shorts GLint, GLsizei 32-bit integer longi GLfloat, GLclampf 32-bit floating point floatf GLdouble, GLclampd 64-bit floating point doubled GLubyte, GLboolean 8-bit unsigned integer unsigned char ub GLushort 16-bit unsigned integer unsigned short us GLuint, GLenum, GLbitfield 32-bit unsigned integer unsigned long ui
Hasonló előadás
© 2024 SlidePlayer.hu Inc.
All rights reserved.