Visa ett inlägg
Gammal 2018-08-12, 02:22   #76
korvtiger
Medlem
 
Reg.datum: Jan 2008
Ort: Uppland, Sverige
Inlägg: 2 716
Standard

Tack för glada tillrop!

-----

Nu blir det en liten parentes till Sa-bygget.

På förfrågan så tänkte jag försöka förklara normalmapping lite närmare.
Detta är som jag varit inne tidigare ett lite abstrakt och svårgreppat koncept då det involverar en del matematik. För er som verkligen vill veta mer om matematiken bakom och hur man implementerar det i en egen grafikmotor rekommenderar jag denna tutorial: https://learnopengl.com/Advanced-Lig...Normal-Mapping.
Jag tänker försöka förklara det mer ur en modellerares perspektiv. För jag lovar att man inte behöver veta särskilt mycket avancerad geometri för att kunna använda normalmapping!

Men vi börjar från början: vad ska man ha en normalmap till?
Jo en normalmap används för att lägga till detaljer på ytan på de trianglar som ett objekts mesh består av. Så utan att lägga till flera vertiser och trianglar som kostar prestanda kan man lägga till massor av små detaljer och ojämnheter på triangeln - så som nithuvuden och repor - mycket, mycket billigare prestandamässigt än om de modellerats ut för hand. (tänk er bara jobbet att modellera ut alla repor i en plåt med polygoner...) Kolla bara in post #66 i denna tråd för att se vad man kan göra med en normalmap (eller en bumpmap).

Det låter ju bra, men vad sjutton är då en normal?
En normal är en vektor (tänk er en pil) som perkar ortogonalt (vinkelrät) mot en yta. Exempelvis: normalen till golvet i ett hus är en pil som pekar rakt upp. Om du står på golvet kan man säga att du är en normal till govlet. Normalen till en vägg pekar rakt ut från väggen, osv...
normalvektor.jpg
Som 3D-modellerare är begreppet normal redan bekant då det är det hållet som en triangel/polygon pekar åt. En polygon har ju två potentiella normaler, en som pekar rakt upp från ytan åt ena hållet och en som pekar rakt åt motsatt riktning. Så vi måste välja vilket håll polygonen skall peka åt genom att se till att dess normal pekar åt rätt håll.
När vi nu börjar pyssla med normalmapping kommer inte bara varje triangel få en normal, utan varje pixel kommer att ha en normal som kommer att varieras med hjälp av en textur, normalmappen. Man utgår då från triangelns normal och låter normalmappen förändra denna normal i varje pixel för att kunna skapa små ojämnheter i ytan.

Vi börjar med att jämföra de två teknikerna bumpmapping och normalmapping med hjälp av ett av SJs gamla monogram som de använde på de teakklädda personvagnarna:
explanation.jpg

Först och främst ser vi ser att bumpmapping och normalmapping ger i princip samma resultat, visuellt.
Till vänster en yta utan någon extra detaljering. Varje pixels normal på denna yta pekar rakt upp, alltså i samma riktning som hela ytans normal. Vi får en platt yta.
I mitten ser vi bumpmapping. Här använder vi en svartvit textur för att definiera höjd. Ju ljusare, ju högre är pixeln upphöjd. Längst ned ser vi hur pixlarna ger olika höjd och ifrån dessa kan grafikmotorn sedan räkna ut ytans lutning. Notera att en bumpmap inte definierar hur högt upphöjd en viss nyans innebär. Detta är helt upp till grafikmotorn att tolka.
Till höger ser vi normalmapping där normalmappen är genererad från bumpmappen. Här ser vi att en normalmap i regel är en väldigt blåtonad textur. Om vi jämför med bumpmappen ser vi att det helvita mitt på monogrammet och den grå bakgrunden har samma färg i normalmappen, en ljus blålila ton. Detta är ytor som är plana och pekar rakt upp. Vi ser att kanterna på monogrammet har olika färg beroende på vilket håll de pekar åt. Till exempel får kanter som pekar åt höger en rosa ton och kanter som pekar uppåt har mer grönaktig ton. I bilden nedtill ser vi hur de olika färgerna tolkas som vektorer som ändrar riktningen på de ursprungliga normalerna. Dessa nya normaler talar om hur den pixeln på ytan lutar. Som en parentes kan vi kan också notera att vi förlorar informationen om en ytas höjd i normalmappen jämfört med bumpmappen.


Så vi har nu sett att en normalmap är någon sorts vektorer (tänk pilar) som pekar ut den riktning som pixelns normal har och att dessa vektorer är inkodade i en blåtonad textur. Men hur fungerar detta?
Jo, för att kunna beskriva en riktning i tre dimensioner behöver man just tre koordinater. Dessa tre koordinater pekar ut en punkt i 3D-rymden. Från koordinatsystemets origo drar men sedan en vektor som pekar på punkten, och vips så pekar den vektorn (som är mycket bra att tänka på som en pil) ut en riktning i 3D-rymden. Notera att det finns oändligt många punkter som skapar vektorer som pekar ut samma riktning. Till exempel genom att fördubbla längden på vektorn, pekar den fortfarande åt exakt samma håll som tidigare, även om det är en annan punkt/vektor. Man brukar därför tala om normaliserade vektorer. En normaliserad vektor är en vektor som har längden 1. Detta gör att varje tänkbar riktning i en 3D-rymd kan beskrivs av exakt en normaliserad vektor. Om man tar alla tänkbara normaliserade vektorer ritar de upp ytan på ett klot med radien 1 runt origo. Om man accepterar detta kan man också förstå att våra tre koordinater i 3D-rymden är allt vi behöver för att beskriva alla möjliga riktningar vi kan tänkas vilja beskriva.

Följande bild förklarar det koordinatsystem som normalmappen utgör:
normalmap_axis.jpg

Så en normalmap är en färgtextur med tre färgkanaler, alltså lika många som koordinater vi behöver för att beskriva en riktning. I bilden ser vi en polygon med normalmappen på. Ytan skapar ett koordinatsystem X, Y, Z som är kopplat till motsvarande RGB-färgkanaler i texturen, så X <-> R, Y <-> G och Z <-> B. X och Y beskriver riktningar i ytan medan Z är normalen till ytan och pekar rakt upp ur ytan. Genom att koda in en koordinat i detta koordinatsystem som en färg kan vi beskriva en vektor som alltså pekar ut riktningen vi vill att normalen skall peka åt i en specifik pixel.

Hur kodar vi då in normalen som en färg?
RGB kodar som bekant färger i 256 nyanser per kanal, så 0-255 för röd, 0-255 för grön och 0-255 för blå färgkanal.
Eftersom vi vill kunna visa riktningar både i X, Y respektive Z's riktningar samt i motsatta riktningar så måste vi mappa om dessa så att halva färgskalan pekar åt motsatt håll. Då blir det så att färgnyansen 255 är så långt åt axelns riktning man kan komma och 0 är så långt man kommer i motsatt riktning. Mitt mellan dessa, värdet 128 är "0-värdet", alltså varken i axelns riktning eller motsatt dess riktning. Notera att värden under 128 på Z axeln (blå färgkanal) alltså ger en väldigt märklig normal som pekar inåt i ytan. Undvik alltså detta!
Med detta förstår vi också varför de flesta ytor på en normalmap är ljust blålila. En oförändrad normal som pekar rakt upp ut ytan (i ytans egen normals riktning) har alltså RGB värdet 128,128,255, vilket innebär ingen utsträckning åt X eller Y, men rakt åt Z. Normalen pekar alltså rakt i Z-axelns riktning och detta är just en ljust blålila färg.

Nu har vi allt vi behöver för att kunna beskriva våra normaler som en färg. Här nedan visas ett exempel med en vektor/normal i vitt som kodas som RGB = 180,90,200. För att hitta vektorn/normalen behöver vi bara följa pilar i X,Y och Z-axlarnas riktning med rätt längd. Notera att X/röd och Z/blå pekar i X- respektive Z-axlarnas riktning eftersom deras färgvärde är över 128, medan den gröna pekar i motsatt riktning eftersom värdet är mindre än 128.
normalmap_vektor.jpg


Förhoppningsvis gav denna post en lite bättre förståelse för normalmapping. Men jag betvivlar att det gjorde er mycket klokare på hur man ritar normalmaps. Men var så lugna! Ingen, inte ens textureringsproffs, målar större delar av normalmaps för hand. Man skapar dem antingen genom att rita bumpmaps för hand (vilket är hur jag gör) och låter ett program som AwesomeBump räkna om det till en normalmap, eller så genererar man dem från en högdetaljerad variant av meshen där alla nitar och detaljer faktiskt är modellerade. Det sistnämnda är dock inget alternativ om man vill ha repor och ojämnheter på varenda vägg i en ånglokshytt som ni kanske förstår. Då får man istället ladda ned PBR texturer från nätet som innehåller färdiggenererade normalmaps och använda dem i sin egen normalmap-textur.

Även om detta är lite off-topic så får ni gärna ställa frågor om normalmapping om ni har sådana. Har ni mycket frågor eller grejer att diskutera så går det givetvis bra att öppna en egen tråd också.

Hoppas detta kan vara till nytta för någon byggare där ute.
__________________
-k-
korvtiger besöker inte forumet just nu   Svara med citat