Az árnyékvetés elve
Az elv egyszerű. Képzeljük el a fényforrást, mint egy kamera valamint a nézeti sugarakat fénysugarakkal helyettesítjük. Így a kamera közelsíkjában képződő képen a fényforrás által látott tér jelenik meg - a rendereléshez használt vetítést a fényforrás típusa határozza meg. Mivel a renderelés közben a mélység tesztet bekapcsoltuk a kapott végeredmény mélység buffere azt az információt fogja tárolni, hogy a fény terében lévő mely térbeli pontok esnek a fényforráshoz a legközelebb és azok milyen távolságra vannak tőle. Ezt a gondolatmenetet folytatva rájövünk, hogy hogyan is keletkezik ebből árnyék. A jelenetet még egyszer renderelve immáron az eredeti kamerából egy egyszerű összehasonlítással el tudjuk dönteni, hogy egy adott térbeli pont és a fényforrás között elhelyezkedik-e egy másik pont - ha ez a feltétel teljesül akkor az adott térbeli pont árnyékban van. Ehhez az összehasonlításhoz két dologra van szükségünk: az adott pont fényforrástól való távolságára és az előző menetben kapott mélység bufferre, amely szintén a fényforrástól mért távolságot tartalmaz. Ha az adott pont távolsága nagyobb, mint a mélység buffer megfelelő helyéről (lásd később) vett távolság érték, akkor az adott pont árnyékban van.
A renderelés tehát mindenképp két menetben zajlik.
Elsőként a fényforrás által látott teret rendereljük le és a vetítés során felhasznált mátrixokat és mélység buffert eltároljuk.
Második menetben a vertex feldolgozáskor két vertex transzformációt hajtunk végre (ne felejtsük, hogy a vetítés, amely egy a transzformációk közül mindössze vertexek és mátrixok összeszorzását jelenti):
- vetítünk a kamera nézetéből .Ennek eredménye lesz végül a látható kép.
- vetítünk a fényforrás nézetéből; ehhez használjuk fel az első menetben eltárolt mátrixokat. Az így kapott transzformált vertexek pedig az előzőleg eltárolt mélység buffer megfelelő helyére fognak mutatni (vagyis oda, ahova a vertex a fényforrásból nézve vetül/vetült) így ezek textúra koordináták használhatók. Fontos megjegyezni, hogy a vetítés eredményeként a vertexek egy (-1,-1,-1)-(1,1,1) kockába kerülnek át így még egy transzformáció szükséges, amely (0,0,0)-(1,1,1) kockába visz át - a textúra tér (0,0)-(1,1) közötti tartományban értelmezett, a mélység pedig (0)-(1) tartományban. Ezt a másodlagos vetítést, az így kapott vertexek textúra koordinátaként való felhasználását és a textúra koordinátákon elvégzett homogén osztást nevezzük projektív texturázásnak.
A vetítések során kiszámolt Z koordináta (ha textúra koordinátában gondolkozunk akkor Z komponens helyett R komponens elnevezés az elterjedt) tartalmazza egyik esetben a kamerától való távolságot másik esetben pedig a fényforrástól való távolságot. Végül nincs más dolgunk csak a mintavételezés a mélység bufferből, a két távolságot összehasonlítani és ezt felhasználni a renderelésben.
Árnyékvetés texture environment combinerrel
Ez az árnyékvetés számos hátránnyal rendelkezik.
- A mélység buffert nem tudjuk felhasználni, hanem nekünk kell egy színcsatornába renderelnünk a távolságot.
- Igen pontatlan a mélységi felbontása mivel a belső feldolgozás során mindenképp 8 bites lesz az általunk számolt távolságérték - annak ellenére, hogy létezik 16 bites színcsatornát támogató textúra formátum.
- Szükségünk van még egy (egydimenziós) textúrára a távolságméréshez - annak ellenére, hogy a Z koordináta tartalmazza a távolságot.
- Az összehasonlítást nekünk kell elvégeznünk.
Árnyékvetés natív hardverrel
Szerencsére ez a megoldás az előző árnyékvetés összes hátrányát kiküszöböli.
- Külön textúra típust biztosít a mélység buffer közvetlen másolásához/tárolásához.
- Általunk választható precizitás - 16, 24 vagy 32 bit.
- Nincs szükség textúrára a távolságméréshez, a Z komponens közvetlenül használható.
- A TMU képes összehasonlítást végezni egy mintavételező regiszter Z kompononse és a mintavételezett érték között; így a mintavételezés eredménye nem az érték lesz, hanem egy boolean (0 vagy 1) érték.
Az OpenGL szempontjából nézve ez az alábbi extension-öket jelenti.
- GL_ARB_depth_texture: ez teszi lehetővé, hogy az adott textúra a négy komponenst nem négy GL_UNSIGNED_BYTE-ként fogja felhasználni, hanem egy GL_UNSIGNED_SHORT ill. GL_UNSIGNED_INT-ként.
- GL_EXT_shadow_funcs ill. GL_ARB_shadow: ez teszi lehetővé, hogy a mélységi összehasonlítás be-/kikapcsolható legyen.