Ezt a bejegyzést azért hoztam létre, hogy a tutoriálokhoz hozzá lehessen szólni (ha valami visszatarthatatlan mondanivalótok lenne).
Vágás-befedés és Carmack's reverse
2012.10.17. 13:22 | darthasylum | Szólj hozzá!
Magától nem jönne rá egy átlagember, hogy hogyan is lehet a stencil bufferrel befedni egy megvágott objektumot. Kis guglizás után az alábbi algoritmust találtam:
- depthbe kirajzolni a vágósíkot
- depth írást lekapcsolni, stencilt be
- front faceken depth pass esetén incr
- back faceken depth pass esetén decr
- kirajzolni a síkot equal operátorral és 1 referenciával
A probléma az ezzel, hogy ha a kamera közeli vágósíkja kettévág egy objektumot, ott nem lesz megfelelő számú increment, és így zfightinghoz hasonló jelenséget tapasztalhatunk.
Itt jön a képbe a Carmack's reverse nevű technika, azaz ne a depth pass-on növeljük a stencilt, hanem a depth fail-en. Az algoritmus az alábbira módosul:
- depthbe kirajzolni a vágósíkot
- depth írást lekapcsolni, stencilt be
- back faceken depth fail esetén incr
- front faceken depth fail esetén decr
- kirajzolni a síkot lessequal operátorral és 1 referenciával
Az eredmény magáért beszél. Az egyetlen problémát a nem kétoldalú felületek okozhatják (pl. billboard).
Subpixel Morphological Anti-aliasing
2012.10.14. 16:16 | darthasylum | Szólj hozzá!
Úgy hozta az Erő, hogy le kellett implementálnom a Crysis 2-ben is alkalmazott SMAA-t. Mint tudjuk, az MSAA (multisample anti-aliasing) nem működik jól a deferred renderinggel, ezért találták ki azt, hogy akkor egy postprocess lépésben simítsuk el az éleket. Ez a technika annyira aktuális, hogy az NVidia driverekben hardveresen le is van implementálva (FXAA), bár a minösége megkérdőjelezhető, ugyanis mindent antialiasol, azt is amit nem kéne.
Na de mi is ez a SMAA? A hasonló módszerekhez képest megpróbálja a lehető legpontosabban rekonstruálni az éleket, és kiszámolni a lefedettséget (coverage). Sőt, ezt úgy csinálja, hogy a már élsimított képet nem rontja le.
Az 1x-es SMAA egy sima postprocess technika, azaz kér egy képet és élsimítja, semmi egyéb nem kell neki. Átlagos képekre teljesen jól működik ez is, viszont ha már vonalakat is kell élsimítani, akkor problémái vannak. Shader Model 3 mindenképpen kell neki, bár OpenGL-ben meg lehet buherálni, hogy GLSL 1.2-vel is menjen, de úgy nem ad olyan szép eredményt (és kell neki egy bemelegedési idő, amíg kiforgatja a ciklusokat).
A minőséget tovább lehet javítani a temporal supersampling nevű módszerrel, ami annyiból áll, hogy az előző frame eredményét felhasználja az aktuálishoz. Ehhez a jelenetet kicsit fel kell rázni (egyszer jobbra egyszer balra), majd az ezekből kapott élsimított képeket összeblendelni a pixelsebesség függvényében. Huhh. Azaz kell hozzá velocity textúra (amit amúgyis megcsinálnál mondjuk a motion blur miatt) és ajánlott a multiple render target support is.
Igen meghökkentő, hogy az így kapott SMAA T2x technika erősen közelíti a 16-os MSAA-t!! (bal: MSAA, jobb: SMAA)
És itt még nincs is vége a bulinak, ugyanis ez még tovább javítható egy 2x-es MSAA-val, amit értelemszerűen nem csináltam már meg, így kapva az SMAA 4x-et.
Az eltés honlap megszűnt
2012.10.09. 22:39 | darthasylum | Szólj hozzá!
Az eltés honlap nem fog már frissülni, mivel törölték az accountomat (bár a honlap most még megvan, nem tudok belépni). Megpróbálom valahogy átköltöztetni a dolgokat ide.
Aki keresné: http://people.inf.elte.hu/asylum/
Az oldal végleg megszűnt, mostantól minden ide kerül.
Multiple render target és MSAA
2012.09.29. 19:24 | darthasylum | Szólj hozzá!
Elkezdtem integrálni a multiple render target és az MSAA supportot az enginebe. Az eddigi koncepció egy részét ki kellett dobni (push/poprendertarget). Nyilván mint mindig DirectX-el össz 20 sor (és alig kellett módosítani), OpenGL-el viszont több száz...
Két flag van amit meg lehet adni textúra kreáláskor: rendertarget és renderattachment. A megkülönböztetés azért kell, mert míg a rendertargetnek van saját FBO-ja, addig a renderattachmentnek nincs. Azaz utóbbi vagy egy rendertargethez csatolható (ha be volt állítva), vagy a default framebufferhez.
Rendertargetet csak a 0-s unitba lehet berakni, attachmentet viszont bárhova. Ha egy unitba nem akarsz már renderelni, akkor NULL-t kell megadni. Ez megint csak OpenGL-ben a problémásabb, mert detacholni kell az attachmenteket. Az optimalizálhatóság érdekében megadható kétféle flag.
Az egyik flag azt mondja meg, hogy ne detacholódjanak a targetek (mert mondjuk nemsokára használni kell megint). A másik flag pedig arra ad egy hintet, hogy mikor hívjon az engine glDrawBuffers()-t.
Offscreen rendertargetet a CreateOffscreenMSAATarget() metódussal lehet majd csinálni.