játékfejlesztés.hu
FórumGarázsprojectekCikkekSegédletekJf.hu versenyekKapcsolatokEgyebek
Legaktívabb fórumozók:
Asylum:    5448
FZoli:    4892
Kuz:    4455
gaborlabor:    4449
kicsy:    4304
TPG:    3402
monostoria:    3284
DMG:    3172
HomeGnome:    2919
Matzi:    2520

Pretender:    2498
szeki:    2440
Seeting:    2306
Geri:    2188
Orphy:    1893
Joga:    1791
Bacce:    1783
MaNiAc:    1735
ddbwo:    1625
syam:    1491
(C++) DirectX programozás 18. - Direct3D 7. (Alpha Blending) 2006.08.01 06:41


Alpha Blending

Ez a cikk nagyon egyszerűen áttetsző objektumok megjelenítéséről fog szólni. Még mielőtt bármit is elkezdenénk, engedélyezzük az alpha blending-et:

lpD3D_Device->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);
Ezek után pedig megbeszéljük, hogyan is renderel a Direc3D átlátszó testeket. Természetesen semmi hókusz-pókusz nincs, csupán rendereléskor összekeveri a renderelendő objektumunk pixeleljeinek színét a már lerenderelt pixelekével. Azaz egy képpont színe így alakul:

megjelenítendő pixel=objektum egy pontja*forrássúly+képernyőpont*célsúly

Azaz a már renderelt pixeleket és az objektum vetített pixeleit súlyozottan összeadja. Mi következik ebből? Az, hogy például egy ablak renderelésénél ahhoz, hogy lássunk mindent, ami az ablak mögött van, előbb le kell renderelni mindent, ami az ablak mögött van, majd ezután jöhet az ablak megjelenítése! Így egymást kölcsönösen takaró objektumokat nehéz megjeleníteni…

Nézzük most az alapesetet, azaz amikor egy sima objektumot akarunk megjeleníteni mindenféle átlátszóság nélkül. Ekkor nyilván a már renderelt pixeleket nem vesszük figyelembe, ezért ezek súlya 0 lesz, azaz a célsúly 0 lesz. De nyilván az objektum pontjainak színére színezzük a képpontokat, így azoknak a súlyát 1-re állítjuk. Tehát a forrássúly 1 lesz.

Teljesen átlátszó testekre nyilván fordítva van. Ha a pontok helyére semmit nem akarunk renderelni, akkor mindkét súlyt állítsuk 0-ra, így semmelyiket nem fogja figyelembe venni.

Akkor lássuk, hogy a súlyokat hogy lehet beállítani! A forrássúlyt így:

lpD3D_Device->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE);
Itt most 1-re állítottuk, csak a példa kedvéért. A célsúly:

lpD3D_Device->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ZERO);
Ezt pedig ugyancsak a példa kedvéért 0-ra állítottuk. Természetesen ezen konstansok (D3DBLEND_ZERO,stb.) bármelyiknél használhatók.

De nekünk nyílván az kellene, hogy az objektum színének alpha csatornájával tudjuk szabályozni az átlátszóságot! Ez sem okoz nagy problémát, hiszen erre természetesen van lehetőség. De előbb meg kell mondani, hogy ez az alpha csatorna honnan jön. Azaz itt is rendelkezésünkre áll 8 szint az alpha csatorna meghatározására. Akkor példának okáért hozzunk létre egy ilyen vertexet(a forráskódban is ilyen):

struct CUSTOMVERTEX {
      FLOAT x,y,z;
      DWORD color;
      FLOAT tu,tv;
};
Azaz van szín is és textúra is. Itt most a textúrát fogjuk kirakni csupán, a szín lényegtelen lesz, csak az alpha csatornáért fog felelni. Tehát a test végső színe így fog alakulni:

lpD3D_Device->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_SELECTARG1);
lpD3D_Device->SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE);

Azaz csak a textúrát vesszük figyelembe. Az alpha csatorna pedig csak a színből fog jönni:

lpD3D_Device->SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_SELECTARG1);
lpD3D_Device->SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_DIFFUSE);
Jól látszik, hogy teljesen analóg módon készíthető alpha blending is, mint texture blending. Azaz itt most az első argumentumot választjuk ki, az pedig most a vertex színe. Természetesen jöhet az alpha a textúrából is, ha van neki(D3DTA_TEXTURE), és ugyanúgy érvényes a moduláció, stb.

Beszéljünk egy kicsit a vertex színéről! Hogy is adható meg alpha csatorna? A vertex színe 32 bitből áll, ezek nyolcas csoportban. Ebből az első nyolcas csoport az alpha csatorna, ennek 0 értéke teljes átlátszóságot jelent(nem biztos, attól függ hogyan nézzük, de ez az általános felfogás, hiszen a súlyoknál(lásd előbb) fordítva is beállíthatjuk), ff értéke pedig azt jelenti, hogy a felület egyáltalán nem látszik át. Ekkor:

0x7f000000

Egy félig átlátszó színt jelent.

Na, ha már van alpha csatornánk, akkor már csak az átlátszóságot kellene megvalósítani. Ugye a végső szín, és a végső alpha csatorna a blending operációkból jönnek, ezért azt kell figyelembe venni. De ezt most úgy állítottuk be, hogy lényegében a szín a textúrából van, az alpha csatorna pedig a vertex színéből. Ezt csak azért írtam le, hogy tisztában legyünk a fogalmakkal.

Tehát a végső átlátszóságot az fogja biztosítani, hogy a forrássúlyt beállítjuk az objektumunk alpha-jára, ami most ugye a vertex színéből jön. Azaz

lpD3D_Device->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
Itt a D3DBLEND_SRCALPHA azt jelenti, hogy a forrás alpha-ját vesszük figyelembe, nem a célét(képernyő). Nyilván a célsúlyt teljesen logikusan ennek inverzére állítjuk(súly szempontjából ez 1-forrásalpha):

lpD3D_Device->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
Ezzel végül is egy gyönyörűen áttetsző tárgyat kapunk. Természetesen az egyes vertexek alpha csatornáit a vertexek között a Direct3D interpolálja.

Akkor itt a forráskód:

d3d6.exe


2006. február 25.

Crusader


Kapcsolódó linkek:

A cikksorozat további részei:

Értékelés: 0

Új hozzászólás
Nincs megjegyzés