Realistisk 3D-grafik. En översikt. Jonas Yngvesson LYSATOR, LiTH Detta är i princip en översatt och förkortad version av artikeln Realism in Computer Graphics: A Survey av John Amanides i IEEE Computer Graphics & Applications Januari 1987. Bakgrund Försöken att visa realistiska bilder på en datorskärm började på det tidiga 70-talet, då priset på minnen gjord att rastertekniken blev prismässigt intressant. Vektorskärmar som dominerat dittills kunde bara visa ett visst antal linjer och, i bästa fall, bara ett fåtal färger. Forskningen hade mest inriktat sig på att ta bort skymda linjer från objekt som skulle visas på en vektorskärm. Dessa bilder var inte realistiska, men lämpade sig bra för t ex CAD. Rastertekniken, som delade upp skärmen i pixels, gjorde att man kunde fylla hela fält med färger av olika intensiteter och nyanser. Rendering Processen att ta en tredimensionell modell av en scen och skapa en tvådimensionell array av pixels med olika intensitet kallas rendering. Objekten i scenen byggs oftast upp av polygoner. Scenen innehåller också ljuskällor, oftast punktformade och placerade utanför synfältet. Slutligen måste punkten som scenen betraktas ifrån definieras för att bestämma vad som ska synas på skärmen. Renderingen (?) börjar med att man transformerar objekten till ett vy-koordinatsystem och det som hamnar utanför synfältet klipps bort. Efter en perspektivtransformation jämförs sedan objekten för att se vilka objekt, eller delar av objekt, som är synliga. När alla synliga ytor hittats, ska dessa brytas ner till pixels och skuggas korrekt. Då får man ta hänsyn till alla ljuskällors placering och intensitet. De olika ytornas position, orientering och egenskaper måste också räknas med. Olika egenskaper kan t ex vara deras färg och hur bra de reflekterar ljus. Eliminering av skymda ytor För att lösa problemet med att ta bort skymda ytor har flera algoritmer föreslagits. Grundidén i alla är dock sortering av något slag. Sorteringen kan ske på pixelnivå eller på polygonnivå. Ofta vill man utnyttja koherens av något slag för att minska beräkningstyngden. Om en polygon är synlig i en pixel, är t ex chansen stor att den är synlig även i intilliggande pixels. Tre vanliga algoritmer är z-buffert, prioritets- och sveplinjealgoritmen. Med z-buffert används en separat 2D array för att lagra djupet på den pixel som har skrivits in på motsvarande plats i bildminnet. För varje pixel som ska skrivas in, jämförs dess djup med det värde som finns lagrat i z-bufferten. Ligger den närmre betraktaren skrivs den in, annars inte. Prioritetsalgoritmen sorterar själva polygonerna i ordning bakifrån och framåt. De skrivs sedan in i bildminnet i den ordningen. Polygoner som ligger närmre betraktaren kan då skriva över polygoner som ligger längre bort. Denna algoritm är inte lika minneskrävande som en z-buffert, men sorteringen kan bli ganska komplicerad. Sveplinjealgoritmen slutligen, finns det flera varianter av. Gemensamt för dem är att de först sorterar polygonerna i xy-planet och sedan löser problemet med skymda ytor för en sveplinje i taget. Detta reducerar problemet från polygoner till linjer, vilket gör det avsevärt lättare. Ofta försöker man utnyttja koherens mellan linjerna. Det är stor chans att polygonerna som var synliga på en linje även är synliga på nästa. Skuggning För att göra en realistisk bild är det viktigt att belysning och skuggor blir naturtrogna. Belysningen i en scen kan delas upp i två delar: - Diffus belysning - Riktad belysning Diffus belysning kommer inte från någon specifik ljuskälla. Den träffar alla delar av alla objekt med samma intensitet. Den är ett slags grundbelysning i bilden. Enbart diffus belysning ger inget realistiskt intryck. Det blir t ex omöjligt att skilja en sfär från en cirkelskiva. Den riktade belysningen är den som kommer från de ljuskällor man har definierat för scenen. Detta ljus träffar vissa ytor av objekten och reflekteras sedan olika beroende på ytans orientering. Man skiljer på två typer av reflexion: - Diffus reflexion - Speglande reflexion Den diffusa reflexionen sprids lika i alla riktningar. Intensiteten hos det reflekterade ljuset varierar som cosinus för vinkeln mellan ytans normalvektor och riktningen till ljuskällan. Detta kallas Lamberts lag. Om man definierar två normaliserade vektorer, L 1) och N, där N är ytans normalvektor och L pekar mot ljuskällan, så beräknas cosinus för vinkeln mellan dem, a, som skalärprodukten L * N. Den speglande reflexionen är något mer komplicerad eftersom den beror av varifrån man betraktar ytan. Om vi inför ytterligare en vektor E som pekar mot betraktaren får man den speglande komponenten som: W(i) COSn(alfa) W(i) är en koefficient som beror av ljusets infallsvinkel i, samma vinkel som för den diffusa delen alltså. Denna koefficient har dock ignorerats eller satts till en konstant i de flesta implementationer. alfa är vinkeln mellan E och L och n är ett heltal som beskriver hur blank ytan är. Den brukar variera mellan 1 och 200. Ju större n, desto blankare yta. Detta är ingen fysikalisk modell, utan är empiriskt framtagen av Bui Tuong Phong. Genom att summera dessa tre komponenter fås intensiteten för polygonen i fråga. Om man fyller hela polygonen med samma intensitet får dock objekten ett kantigt utseende. Särskilt om polygonerna är stora. För att åtgärda detta föreslog Gouraud att man skulle beräkna intensiteten i varje hörn av polygonen, och sedan interpolera mellan dessa värden. Det tar bort kantigheten men tar också bort mycket av blankheten. Phong föreslog istället att man skulle interpolera normalvektorena mellan intilliggande polygoner. Detta är mer beräkningskrävande men ger mycket realistiska bilder även för ganska stora polygoner. Texturmappning Riktigt verklighetstrogna bilder kräver ofta mycket komplexa objekt. En persisk matta eller en marmorskiva är exempel på det. Att försöka representera dessa komplicerade mönster med polygoner skulle bli mycket beräkningskrävande. För att gå runt detta används texturmappning. Man låter då hörnen i polygonerna få koordinater i en 2D array av färger som innehåller mönstren. Genom at använda dessa färger vid skuggningen kan man "tapetsera" polygonerna med mönstret. Man kan också låta mönstret representeras av en funktion som tar ett koordinatpar som argument. Man kan på så vis mappa t ex en fraktalkurva på ett objekt. Mönstren behöver inte vara tvådimensionella. Genom att låta mönster variera en aning även i höjdled har man framgångsrikt Iyckats simulera bl a bark på trädstammar och grenar. Strålföljning På senare tid har mycket forskning inriktat sig på optiska effekter och strålföljning (raytracing). Anledningarna är främst två. Dels är dessa effekter mycket viktiga för verklighetstrogna bilder och dels är lösningen (strålföljning) mycket enkel, både begreppmässigt och algoritmiskt. I strålföljning låter man en tänkt stråle gå från ögat genom en pixel på skärmen och in i scenen. Om strålen träffar ett objekt låter man den reflekteras och, om objektet är genomskinligt, även brytas in i objektet. Man tar hänsyn till hur blankt objektet är och dess brytningsindex. Man följer sedan dessa två strålar på samma sätt. Genom att sedan gå baklänges i det genererade strålträdet och beräkna bidragen från alla objekten fås den slutliga intensiteten för pixeln. Denna beräkning sker med en modell som är mycket lik den tidigare beskrivna Phongs belysningsmodell. Detta upprepas för samtliga pixels på skärmen. En stor nackdel med strålföljning är att det är mycket beräkningskrävande. Skälen för detta är flera. För det första förlorar man all koherens när varje stråle följs obroende av alla andra, och för det andra är kontrollerna om en stråle träffar ett objekt besvärliga. De består ofta av flera flyttalsberäkningar, t ex att finna rötter till polynom. Det finns förstås fördelar också. Skymda ytor tas om hand automatiskt, perspektiv likaså och man behöver ofta inte dela upp objekten i polygoner utan kan låta dem ha sin naturliga representation. Resultaten blir ofta extremt realistiska bilder. Modellering De flesta system arbetar som sagt med polygoner när de genomför transformationer, skuggningar etc. Tyvärr är det komplicerat och tidsödande för en användare att modellera komplexa objekt med sådana primitiver. Man behöver någonting på en högre nivå. Några av de mest populära primitiverna på högre nivå är parametriska ytor, eller splines. Dessa ytor är parametriska för att vara oberoende av orientering. De består typiskt av kubiska polynom eftersom dessa är tillräckligt lätta att specificera mer samtidigt kraftfulla nog att beskriva de flesta buktiga ytor. Det finns flera varianter på detta tema. De har olika sätt att specificera formen på ytan och alla försöker ge användaren enkla, intuitiva men ändå kraftfulla metoder för detta. Ofta består de i att man specificerar ytan med ett antal kontrollpunkter och utifrån dessa beräknas sedan koefficienter för polynomen. En annan metod är att avända solider. Man bygger då upp objekten med volymprimitiver som sfärer, kuber och cylindrar. Detta är speciellt populärt inom CAD/CAM. Skymda ytor behandlas tämligen enkelt med t ex någon variant av sveplinjealgoritmen. Några av de svåraste problemen är att modellera naturliga objekt som tex moln, terräng och eld. Objekt skapade av människor har oftast en viss regelbundenhet medan naturliga ofta har en hög komplexitet och "slumphet" i sig. Följaktligen har många försökt hitta någon slags stokastisk modell för att beskriva dem. Man har ansträngt sig mer att få utseendemässigt acceptabla bilder än att få processerna att vara vetenskapligt korrekta. För att skapa terräng har föreslagits en metod som bygger på att man tar en parametrisk yta och sedan adderar en slumpprocess. Den parametriska ytan får då beskriva huvuddragen, typ var det ska vara berg och dalar, medan slumpprocessen ger detaljer. En annan metod är att utgå direkt från en slät triangel och sedan sönderdela den och låta en slumpprocess förflytta ändpunkterna på undertrianglarna en bit. För att approximera eld har använts något som kallas partikelsystem. Ett partikelsystem är en process som slumpartat genererar en serie punkter med rörelse. Användaren definierar ett slags medeltal för genererade partiklar med deras livstid, hastighet och färg. Slumpprocessen genererar sedan, ofta flera tusen, partiklar där var och en får sin egen livstid, hastighet och firg. På skärmen representeras partiklarna av raka streck. Genom att ha flera sådana system och summera ihop bidragen från alla partiklar till varje pixel kan övertygande bilder av explosioner och eld skapas. Liknande teknik har använts för att generera gräs, träd och blad. Träd och växter har också skapats med ett slags grammatik. Man anvander ett fommellt språk baserat på biologers beskrivning av förgreningsmönstret hos trad. Språkets produktionsregler genererar en sträng som beskriver ett visst träd. Med ett program som tolkar denna sträng kan sedan trädet genereras. Med olika produktionsregler får man olika sorters träd. Med hjälp av en slumpprocess kan dessutom varje träd få ett individuellt utseende. Slutord Det finns flera viktiga problem som inte tagits upp här. Aliasing och olika samplingsproblem är några av de viktigaste. Om intresse finnes kanske jag tar upp dem i en kommande artikel. Man har nu kommit så långt att datorgenererade bilder duger att använda för specialeffekter i vissa filmer och reklam. Någon "perfekt" lösning har dock inte hittats. Allmänt har datorgenererade bilder en tendens att se för bra ut. Inget damm eller skräp i hörnen. Alltid raka linjer och perfekta släta ytor. Enkla scener utan någon detaljrikedom. Även dessa begränsningar måste övervinnas för att åstadkomma verklig realism. 1) I den här artikeln betecknar bokstäver i fetstil vektorer.