HTML

Az élet kódjai

Csináld maga. Senki nem csinálja meg helyetted.

Friss topikok

Framebuffer és Textúra

2011.03.29. 18:27 Travis.CG

Korábban bemutattam, hogyan lehet egy OpenGL keretrendszert létrehozni X11 alatt. Most röviden bemutatom, hogyan használom a Framebuffert, hogy ne csak a képernyőre rajzoljak. Miért lehet szükség arra, hogy ne a képernyőre rajzoljunk, hanem a memóriába? Először is, azért, mert további műveleteket végezhetünk a memóriában tárolt képen, mielőtt a nézők szeme elé tárulna a látvány.

Az egyik ilyen művelet az élsimítás, de a deferred rendering nevű eljárás is ezen alapul. Hosszú távon nekem ez utóbbi a célom. Amint elég tapasztalatom lesz a témával kapcsolatban, arról is írok egy bejegyzést. A környezet továbbra is OpenGL 4.1

Inicializálás

Az első lépés, hogy hozzuk létre saját framebufferünket a glGenFramebuffers segítségével. Nagyon hasonló, mint amit textúránál is csinálunk. Rögtön utána kössük is magunkhoz a glBindFramebuffer segítségével. Az első paraméter általában GL_FRAMEBUFFER lesz. Akár mit is akarunk kezdeni a framebufferünkkel, egészen biztos, hogy szükségünk lesz egy mélységi pufferre. Ha ezt nem hozzuk létre, a takarásban lévő és látható pixelek összekeverednek és nagyon ronda eredményt adnak. Tehát kell egy mélységi puffer.

A glGenRenderbuffers hasonlóan működik, mint a glGenFramebuffers. Ezt is kössük (glBindRenderbuffer), majd meghatározzuk a méretét. a glRenderbufferStorage-val. Az első paraméter a két utolsó függvénynél GL_RENDERBUFFER lesz. Más nem is lehet. Mivel mélységi puffert akarunk, ezért a glRenderbufferStorage második paramétere GL_DEPTH_COMPONENT lesz.

glGenRenderbuffers(1, &rb);
glBindRenderbuffer(GL_RENDERBUFFER, rb);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, szelesseg, magassag);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb);

Az utolsó lépésben a frissen keletkezett pufferünket hozzárendeljük a framebufferhez. A gyakorlatban csak a második és utolsó paramétert szokták változtatni, ha esetleg más komponenshez is puffert rendelnek. Más komponenshez? Igen! Lehetőségünk van több szín, mélység és stencil pufferbe tárolni információt. A színpufferek száma implementáció függő, a GL_MAX_COLOR_ATTACHMENTS ad róla információt.

Bár minden fórumon és blogban azt olvastam, hogy ahol csak lehet, használjunk renderbuffereket, véleményem szerint a mélységi komponens kivételével (sőt, deferred shading esetén ott sem) ne használjunk renderbuffert. Mégpedig azért ne, mert az ott tárolt információt csak arra használhatjuk, hogy kitegyük a képernyőre. Márpedig egy demóban még sokat kell játszani a képpel, hogy azt ki merjük rakni a képernyőre. De akkor hogy lehet utólagos effekteket rárakni a tárolt pufferre? A renderbuffer mellett van egy másik lehetőségünk. Textúrát is köthetünk a framebufferhez! A textúra pedig könnyedén bemenete lehet egy shadernek, amivel már megbolondíthatjuk a képet. Ezért gondolom úgy, hogy nem érdemes renderbufferekkel foglalkozni.

Textúrák hozzákötése kísértetiesen hasonlít a renderbufferek kötéséhez:

glGenTextures(1, &t);
glBindTexture(GL_TEXTURE_2D, t);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, szelesseg, magassag, 0, GL_RGBA, GL_UNSGINED_BYTE, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, t, 0);

Természetesen a textúrák esetén még nagyon sok paramétert be lehet állítani, de azokat kihagytam, mert tele velük az internet. Amire itt felhívnám a figyelmet, az a GL_COLOR_ATTACHMENT0. Ez azt mondja meg, hogy a számtalan színpuffer körül mi az elsőt kötjük össze a megadott textúrával. Ennyi.

Használat

Amennyiben használni szeretnénk pufferünket, tegyük a következőt:

glUseProgram(puffershader);
glBindFramebuffer(fb);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
...rajzoló rutinok...

Természetesen a képernyőn nagy feketeség fog megjelenni. Régen, mikor még nem voltak pufferjeink, akkor is tudtunk textúrába renderelni, majd négyszöget rajzoltunk, ami lefedte a képernyőt és ráhúztuk a textúrát. Ennek vége. (Igazából nem. Sok esetben még mindig egyszerűbb így rajzolni) A pufferünket egy lépésben (pontosabban három, ha az utasítások számát nézzük) a képernyőre rakhatjuk a glBlitFramebuffer segítségével.

glBindFramebuffer(GL_READ_FRAMEBUFFER, fb);
glBindFramebuffer(GL_WRITE_FRAMEBUFFER, 0);
glBlitFramebuffer(0, 0, szelesseg, magassag, 0, 0, szelesseg, magassag, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_LINEAR);

Mint a paraméterekből kikövetkeztethető, nem muszáj a teljes képernyőt kitölteni. Ez érdekes effekt ötleteket adhat az embernek. A 0 jelű framebuffert tartja fenn a rendszer a képernyőn megjelenő képnek. Lehet több framebufferünk is, a fenti megoldással tetszőleges két framebuffer között tudunk másolni.

Szólj hozzá!

Címkék: programozás demoscene

A bejegyzés trackback címe:

https://cybernetic.blog.hu/api/trackback/id/tr102776325

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

Nincsenek hozzászólások.
süti beállítások módosítása