Jeni László Attila jedi@inf.elte.hu Klár Gergely tremere@elte.hu „Mappings” 2. Jeni László Attila jedi@inf.elte.hu Klár Gergely tremere@elte.hu
Miről lesz szó? Bump mapping, Normal mapping Displacement mapping Environment mapping
Bucka és normál leképzés Feladat: részletgazdagabbá akarunk tenni egy felületet, hogy apró egyenetlenségek is meglátszódjanak rajta, miközben a geometriát nem akarjuk megváltoztatni
Bucka és normál leképzés Tároljuk a felületi normálvektor perturbációt egy térképben. Ezeket az információkat felhasználva árnyalásnál módosítjuk a visszaverődő S vektor irányát (és ezáltal a megfigyelő által észlelt fényerő mértékét). Nem módosítunk a geometrián.
Bucka és normál leképzés Bucka térkép Normál térkép
Bucka leképzés
Bucka térkép előállítása A nagyobb tesszellációval rendelkező modell segítségével meghatározhatjuk a bucka térképeket a kisebb tesszelláltságú modellhez.
Bucka térkép előállítása Procedurális textúrák segítségével http://www.filterforge.com/ Rajzoló programmal http://nifelheim.dyndns.org/~cocidius/normalmap/ http://developer.nvidia.com/object/photoshop_dds_plugins.html
Normál térkép használata A kép RGB csatornáin XYZ értékeket tárolunk Ezek értéke [0,1] tartományban lehet De egy normálvektor koordinátái [-1, 1] között vehetnek fel értéket! NormalVector = (NormalTexture-0.5)*2
Normál térkép használata Az így kapott vektor adja az adott pontbeli normálvektor. Probléma: fontos a normál térkép sodrása! Jobbkezes térkép balkezes rendszerben hibás árnyékokat eredményez, és viszont!
Textúra és világ koordináta rendszerek A normál térképben tárolt vektorok a textúra síkjához képest adottak, azaz helyes értéket (transzformációk nélkül) csak az XY síkon fekvő, és a +Z felelő néző objektumokra adnak
Normál térképek transzformálása (Texture-Space Normal Mapping) A probléma, hogy a textúra-tér és az objektum-tér inkonzisztens egymással Egy megoldás, ha az fény számításnál használt vektorokat (directionToLight, directionToCamera) elforgatjuk a textúra-térbe. Ez csak ritkán használható megoldás, mivel az elforgatás csak objektumonként adott, de nekünk felületenként (gyak. háromszögenként) lenne rá szükségünk
Texture-Space Normal Mapping
Normál, tangens, bitangens Egy forgatási mátrix megadható a fenti három vektor segítségével Célunk, hogy a textúra-tér XY síkja a „normál leképezés alá kerülő” háromszög síkjába kerüljön Ha ismert a fenti három vektor, akkor belőlük képzett forgatási mátrix pontosan ezt a transzformációt végzi el.
Normál, tangens, bitangens vektorok számítása Ha a háromból kettő adott, akkor a harmadik számítható az alábbi képletek alapján: N általában adott Sok 3D-s program támogatja a tangens és/vagy bitanges exportálását A bitangest (tévesen) szokás néha binormálisnak is nevezni
További olvasnivalók Leírás a bucka illetve normál leképezésekről, shader kódokkal: http://http.developer.nvidia.com/CgTutorial/cg_tutorial_chapter08.html Tangens, bitangens vektorok számítása: http://www.terathon.com/code/tangent.html
Eltolás leképzés Displacement mapping A textúrázást felhasználhatjuk arra is, hogy elmozdítsuk az objektum felületi pontjait.
Előnyök, hátrányok Valóban megváltoztatja a felület geometriáját, nem csak azt az érzetet kelti Ellenpélda normál leképezésnél: Csak annyira lesz részletes, amennyire a felület felbontása az:
Környezet leképzés Tükröző és törő felületű objektumok modellezésére használhatjuk. Nem szükséges hozzá pontos fizikai modellezés Visszaverődő sugár: A kamerából induló nézeti fénysugár és az objektum metszéspontjához a visszaverődő fénysugár és a közvetítőfelület metszéspontját rendeljük (environment mapping ).
Környezet leképzés Gömbi leképzéssel:
Környezet leképzés Blinn-Newell leképzéssel:
Környezet leképzés Kocka leképzéssel:
Kocka textúrák A kocka textúrák (cube maps) különleges, hat lapból álló textúrák, amik három koordinátával címezhetők. A hat lap a +X, -X, +Y, -Y, +Z, -Z irányoknak felelnek meg, mindegyik egy lapja a kockának.
Környezet leképzés, tükröződés A kocka leképzéssel bonyolult transzformációk nélkül megkaphatjuk a textúra koordinátákat. Az kocka textúra megfelelő pontját a kamerába mutató vektor normál vektorra vett tükörképe adja. A kapott pontból kell olvasni a textúrából float3 R = reflect(-directionToCamera, input.Normal); float4 envColor = texCUBE(envMapSampler, R);
Környezet leképzés, fénytörés Hasonlóan járunk el, mint a tükröződés esetén Fénytörés során, a sugár elhajlását a Snellius–Descartes-törvény adja, ami szerint Az kocka textúra megfelelő pontját a refract függvény adja. A kapott pontból kell olvasni a textúrából float3 R = refract(-directionToCamera, input.Normal, 1.01); float4 envColor = texCUBE(envMapSampler, R);
További környezet leképzésen alapuló technikák Chromatikus diszperzió R,G,B csatornánként külön számítjuk a fénytörés, kissé eltérő törésmutatókkal. Példa kód: float4 envColor = 1; float3 R = refract(-directionToCamera, input.Normal, 1.01); envColor.r = texCUBE(envMapSampler, R).r; R = refract(-directionToCamera, input.Normal, 1.04); envColor.g = texCUBE(envMapSampler, R).g; R = refract(-directionToCamera, input.Normal, 1.07); envColor.b = texCUBE(envMapSampler, R).b;
További környezet leképzésen alapuló technikák Fresnel hatás Egyszerre használunk tükröződést illetve fénytörést A visszavert és átengedett fény arányát a beesési szög és az anyagjellemzők határozzák meg Példa kód: float power = 5; float reflectionCoefficient = max(0, min(1, 1-pow(dot(directionToCamera, input.Normal), power))); float3 Rfl = reflect(-directionToCamera, input.Normal); float3 Rfr = refract(-directionToCamera, input.Normal, 1.05); float4 envColor = reflectionCoefficient*texCUBE(envMapSampler, Rfl)+(1-reflectionCoefficient)*texCUBE(envMapSampler, Rfr);
További környezet leképzésen alapuló technikák SkyBox/SkySphere Egy olyan modellt hozunk létre, ami teljesen tartalmazza a színteret, végtelenül távol van, elérni nem lehet, de „forgásra” változik. Ehhez a verex shader-ben a modellt eltoljuk a hátsó vágósíkhoz, textúra-koordinátáknak pedig a csúcspontok eredeti pozícióit használjuk.
További környezet leképzésen alapuló technikák SkyBox/SkySphere Példa kód: void VertexShaderFunction(float3 Position : POSITION0, out float4 SkyPos : POSITION0, out float3 SkyCoord : TEXCOORD0) { float3 worldPosition = mul(Position, World); float3 viewPosition = mul(worldPosition, View); SkyPos = mul(float4(viewPosition, 1), Projection).xyww; SkyCoord = Position; }