Datorgrafik Ray tracing Mattias Ekström, Västerås, 2010-03-05 1
SAMMANFATTNING Ray tracing är en teknik för att skapa bilder digitalt. Den används komersiellt främst inom film- och spelindustrin. Metoden går som namnet antyder ut på att följa strålars väg genom en virtuell värld, eller scen. En av fördelarna med en ray tracer är att man väldigt lätt kan implementera saker som ofta är komplicerade med andra renderingsmetoder, så som reflektioner, skuggor och transparens. Naiva ray tracers är väldigt enkla att implementera men producerar ofta inte särskilt övertygande resultat. Mer avancerade ray tracers kan skapa fotorealistiska bilder men kräver betydligt mer arbete för att skapa och mer beräkningskraft för att köra. Ray tracing lämpar sig väldigt väl för att dels upp i mindre problem som kan exekveras parallellt. Detta gör att man för att rendera långa bildsekvenser som filmklipp använder flera datorer för att rendera samma scen. Man renderar till exempel en del av varje bild per dator, eller en hel bild per dator. Med dagens moderna grafikkort med många beräkningsenheter har ray tracing blivit aktuellt som poteniell ersättare av de metoder som används för rendering av grafik i datorspel. 2
INNEHÅLLSFÖRTECKNING INLEDNING... 4 RAY TRACING... 4 Vad är ray tracing?... 4 Hur går det till... 5 Skuggor... 5 Reflektion och transparens... 5 En enkel beskrivning av algoritmen... 6 Användingsområden... 7 Avancerade metoder... 7 Global Illumination... 7 Prestanda... 8 Parallellism... 8 Andra optimeringar... 8 SLUTSATSER... 9 REFERENSER... 9 3
INLEDNING Ray tracing är en teknik för att skapa digitala bilder. Syftet med denna skrift är att läsaren efter att ha läst den ska ha en grundläggande uppfattning om vad ray tracing är och hur det går till. Den riktar sig till personer som kanske inte sysslat så mycket med datorgrafik och ray tracing i synnerhet, men som ändå har en viss kunskap om matematik och programmering. Först i detta dokument kommer en en beskrivning av vad ray tracing handlar om, vad det används till och hur det implementeras. Därefter följer fördjupning inom vissa mer avancerade tekniker som bygger på ray tracing samt tekniker som typsikt används för att snabba upp algoritmen. RAY TRACING Vad är ray tracing? Ray tracing är som sagt en teknik för att skapa bilder digitalt med hjälp av datorer. I grunden är grundläggande tanken bakom ray tracing mycket enkel, det är därmed inte sagt att det är mycket enkelt att skapa en mordern och snabb ray tracer som skapar bilder av hög kvalitet. Det finns väldigt mycket forskning inom området, speciellt sedan tidigt 80-tal har det skrivits mycket om ray tracing. Ray tracing handlar som namnet antyder om att följa tänkta ljusstrålar [1]. Detta görs genom en så kallad scen i datorns minne som kan bestå av olika objekt, t.ex. sfärer, cylindrar, kuber eller trianglar. Genom att följa dessa tänkta ljusstrålar genom scenen får man i slutändan en bild i datorns minne av hur scenen ser ut. En av de stora fördelarna med ray tracing är att det är väldigt lätt att rendera reflektioner, skuggor och transparens, något som med scanline rendering är väldigt komplicerat. Figur 1: En ray tracad bild som tydlig visar skuggor och transparens 4
Hur går det till I enklare ray tracers utgår strålarna från en tänkt kamera och fortsätter sedan ut i scenen. Man tänker sig ofta ett rutnät framför kamerans position där varje ruta i nätet motsvarar en pixel d.v.s. bildpunkt i bilden. Man skjuter en stråle från kameran genom varje ruta i nätet, varje stråle motsvarar då en bildpunkt i den slutgiltiga bilden. Därefter jämför man strålens väg genom den tänkta världen mot alla objekt för att hitta möjliga kollisioner. Om strålen kolliderar med ett objekt vet man kan se det objektet från kameran, det finns således med i bild. Man vet även vilken del av objektet som träffats och därmed också vilken karaktär materialet vid kollisionspunkten har. Om materialet är blått fyller man i en blå bildpunkt på sin bild. Detta ger dock inte något vidare tillfredsställande resultat, man får t.ex. inga skuggor eller reflektioner och bilden ser väldigt platt ut eftersom ytorna saknar skuggning. Skuggor För att få skuggningar av ytor använder man ofta två olika metoder samtidigt. En metod för att beräkna hur mycket ljus som belyser punkten utifrån ljusets position och riktning i förhållande till normalen vid kollisionspunkten. Detta är en så kallad lokal belysningsmodell och populära alternativ för enklare implementationer är blinn- och phongshading. Man använder även en metod för att se om kollisionspunkten belyses över huvud taget. Detta görs genom att man skjuter en stråle från kollisionspunkten mot ljuset, om strålen träffar något objekt på vägen som inte är ett ljus vet man att kollisionspunkten ligger i skugga [3]. Har man flera ljus i samma scen upprepar man detta för varje ljus i scenen. Reflektion och transparens Att bara ha helt diffusa objekt kanske inte är så roligt, som tur var är det relativt enkelt att implementera reflektioner och transparens i en ray tracer. Om man har skjutit en stråle och träffat ett reflektivt material gör man bara så att man först beräknar en vektor som är infallsvinkeln speglad runt normalen vid kollisionspunkten. Därefter skjuter man en ny stråle ut i scenen från kollisionspunkten med den reflektionsvektor som nyss beräknades som riktning. Det färgvärde man får från denna stråle tas med i beräkningen för färgvärdet vid den ursprungliga kollisionspunkten. Som ni kanske märkt är detta en rekursiv process då även den reflekterade strålen kan träffa ett reflekterande material. Transparens fungerar väldigt mycket på samma sätt som reflektioner, men istället för att skjuta den nya strålen ut från objektet beräknar man istället en vektor som passerar genom objektets yta och fortsätter sin väg inuti objektet. När den sedan träffar en objektet igen från insidan, beräknar man en ny vektor och strålen fortsätter sin väg genom scenen. Vilken riktning dessa vektorer har beror på materialet som träffas brytningsindex. 5
En enkel beskrivning av algoritmen Nedan följer en beskrivning av algoritmen i form av pseudokod: 1 För varje bildpunkt: 2 Skjut en stråle in i scenen 3 Om strålen träffar ett objekt 4 För varje ljus 5 Skjut en stråle mot ljuset 6 Om strålen når ljuset 7 Belys bildpunkten 8 Annars 9 Bildpunkt är i skugga 10 Om ytan är reflektiv 12 Skjut en reflektionsstråle in i scenen 13 Addera resultatet till bildpunkten 14 Om ytan är transparent 15 Skjut en stråle genom objektet 16 Addera resultatet till bildpunkten 17 Annars 18 Fyll i med bakgrundsfärgen Transparens- och reflektionsstrålarna skalas först med materialets transparens- eller reflektionskoefficient innan dom adderas till den slutliga bildpunkten. De är även rekursiva anrop till rad 2 i kodsnutten.som synes är det inte särskilt komplicerat att implementera en enkel ray tracer. Det svåraste momentet ligger i den matematik som krävs för kollisionstesterna mellan strålarna och objekten i scenen. Figur 2: Visar en stråles väg genom scenen. Först skjuts den genom en bildpunkt i nätet framför kamera, sedan reflekteras den i plattan och slutligen träffar den sfären som belyses av ljuskällan. Resultatet blir att sfären visas som en reflektion i plattan. Typsikt sett så defineras strålarna som en vektor som är strålens utgångs punkt samt en vektor som är dess riktning. 6
Användingsområden Ray tracing används framför allt för att skapa bilder, filmklipp och specialeffekter för filmer och annan media. Det används även för visualisering av t.ex. ritningar eller matematiska formler (julia-fraktalen är ett välkänt exempel). Ray tracings användning inom spelutveckling har varit begränsad, framför allt eftersom metoden är tyngre att beräkna och inte hittills lämpats sig för att användas i real-tid, men med nya krafitigare datorer är det på väg att ändras. Det finns mycket skrivet om just användning av ray tracing i realtid. Framför allt handlar det om att använda grafikkort för att utföra beräkningarna, då dom numer består man hundratals mindre beräkningsenheter och ray tracing lämpar sig utmärkt för att göras parallellt. Avancerade metoder En naiv implementation ger ofta väldigt imponerande resultat relativt till mängden kod som krävs för att skapa den, men det är ofta inte bra nog för att användas i t.ex. film och annan media. Vissa naturliga fenomen kräver mer avancerade metoder för att gestaltas med hjälp av ray tracing. Det kan röra sig om hur ljus sprider sig i ett material, t.ex. en människas hud eller hur ljus färgas när det reflekteras i en färgad yta. Även saker sådant som man förväntar sig att se i en bild filmad med en riktig kamera så som områden som är suddiga då dom ligger utanför fokus måste simuleras på vis då en naiv ray tracer renderar allt som om det vore i fokus. Global Illumination Global illumination hänvisar till en grupp tekniker som används för att skapa mer realistiska ljusförhållande i en renderad bild. Det rör sig oftast om indirekt belysning, där ljus studsar mellan olika belysta ytor eller hur ljus som passerar genom ett transparent material belyser det som finns på andra sidan. I en naiv ray tracer följer man strålen i dess väg från kameran till ett olika objekt och undersöker om dessa objekt är inom synhåll från en ljuskälla. Problemet med den metoden är man missar saker som diffusa reflektioner eller hur vattnet bryts genom t.ex. ett glas vatten och skapar mönster på bordet under. Path tracing Path tracing är en metod som är snarlik den naiva ray tracern, men istället för att direkt se om en kollisionspunkt på ett diffust material får ljus från en ljuskälla slumpar man istället vilken riktning man vill fortsätta i [Cassagnabére04]. Från varje träff skjuter man en stråle i vald riktning och undersöker hur mycket ljus som kommer från den riktningen och t.ex. vilken färg ljuset från den riktningen har, detta är en rekursiv process så om den reflekterade strålen skulle träffa ett annat objekt gör man likadant där. Detta förlopp slutar i teorin inte förens någon i kedjan av strålar når en ljuskälla. Om ljuskällorna är små kan rekursiondjupet bli väldigt högt, för att motverka detta slumpar man vid varje träff, beroende på det träffade material, om en man ska forstätta eller se det som att ljusstrålen har absorberats av materialet. Resultatet blir att man får en mer realistisk bild av hur ljus reflekteras i scenen [2]. För att förhindra att bilden blir brusig skjuter man flera strålar för varje punkt i bilden, detta på grund av att en enda reflektionsstråle inte ger en korrekt representation av området kring träffen. Photon mapping Photon mapping är en annan metod för att åstadkomma global illumination. Den fungerar i två olika steg [Jaroz08]. Det första sker genom att man skjtuer massvis med ljusstrålar från ljuskällorna i scenen, man följer sedan deras väg genom scenen och lagrar var dom träffar 7
olika ytor. Ljusstrålarnas karaktär ändras när dom träffar något och reflekteras, dom ändrar i intensitet och färg beroende på den träffade ytans material. Det andra steget är att man man ray tracar scenen normalt, men vid varje träff analyserar man datan man fick från det första steget om hur ljuset sprider sig i scenen och använder detta för att bestämma hur ytorna belyses. Prestanda Ray tracing är väldigt beräkningsintensivt relativt andra renderingsmetoder så som scanline rendering, men resultaten med avancerade ray tracers är oftast mycket mer tillfredsställande. Det har länge varit ett mål att kunna använda avancerad ray tracing i realtid för att kunna rendera realistiska och komplexa scener. För att snabba upp rendering används många olika metoder, det kan handla om allt från att optimera sin kod till att dela upp renderingsarbartet mellan tusentals maskiner. Parallellism På senare år har det blivit aktuellt att använda GPU:er som sitter i grafikkort för att göra många olika typer av tunga beräkningar, en av dom är ray tracing [Purcell05]. Ray tracing är en renderings metod som lämpar sig extremt väl för att göras parallellt då varje stråle är oberoende av de andra och kan beräknas för sig. I nuläget använder dock de största komersiella renderarna vanliga CPU:er för arbetet, dom har dock stöd för att dela upp arbetet mellan flera beräkningsheter och datorer, vilket gör att man ändå kan rendera väldigt komplexa och realistiska scener utan att det tar allt för lång tid. Andra optimeringar Det finns många andra sätt att öka prestandan i en ray tracer, en mycket vanlig metod är att dela in världen i mindre delar så att man istället för att testa varje stråle mot alla objekt (en typiskt scen kan ha hundratusentals eller till och med flera miljoner trianglar) så grupperar man alla objekt i olika hierarkier. Vad man tänker sig som ett objekt i scenen kan bestå av flera tusen olika objekt för ray tracern sett, en kanin som är lätt att se som ett objekt, kanske egentligen består av tusentals trianglar som i sig är egna objekt som ray tracern måste undersöka för varje stråle, detta blir snabbt väldigt långsamt. Man gör istället som så att man grupperar alla dessa trianglar inom t.ex. en bounding sphere. Man säger att kaninens olika delobjekt befinner sig inom denna bounding sphere och testar först strålen mot bounding spheren, träffar man boundingen spheren vet man att man måste gå igenom och testa alla mindre delobjekt också. Men, om man skulle se att man missar bounding spheren kan man skippa tusentals operationer och spara en hel del tid. Man kan också gruppera dessas grupperingar. Om man ser att det finns många av dessa bounding spheres nära varandra kan man lägga ännu en bounding sphere runt dom, och på så vis potentiellt slippa göra ytterliggare beräkningar [4]. Detta ger en stor prestandaförbättrning när man har väldigt många objekt. En annan metod för att dela in scenen i mindre delar som är populär är så kallade kd-träd. Ett kd-träd är snarlikt ett binary tree, men det finns olikheter. I ett kd-träd delas världen i olika delar genom att man hittar plan [Moore91]. Varje plan associeras med en av världens axlar och man väljer en punkt längs planets axel, allt som ligger under denna punkt hamnar i ena subträdet och det som ligger över hamnar i det andra. För att skapa bra och effektiva kd-träd är val av denna punkt väldigt viktigt, dels är det viktigt att trädet blir väl balanserat, annars kan man få beteenden som snarare liknar än länkad lista än ett träd och dels vill man välja punkten som sådan att det maximerar antalet möjligheter att avsluta en sökning genom trädet. 8
SLUTSATSER Ray tracing är en teknik för att skapa realistiska bilder digitalt som i dagsläget inte lämpar sig för realtids tillämpningar. Framtiden ser dock ljus ut för tekniken, det pågår mycket forskning i ämnet och tekniken är redan vida använd komersiellt inom t.ex. filmindustrin. Med paradigmskiftet till flerkärniga datorer och utvecklingen av grafikprocessorer med allt fler beräkningsenheter kommer det nog inte dröja länge innan ray tracing även tar över för realtidsbruk. Naiva implementationer av tekniken är enkla att genomföra, men de producerar inte realistiska resultat och är ofta inte väldigt effektiva. Det går dock att relativt enkelt öka hastigheten på ray tracing genom att tillföra mer beräkningskraft i form av extra beräkningsenheter. REFERENSER [1] Wikipedia Ray Tracing (Graphics). Wikipedia Mars 2010, [5 Mars 2010] <http://en.wikipedia.org/wiki/ray_tracing_(graphics)> [2] Wikipedia Path Tracing. Wikipedia Mars 2010, [5 Mars 2010] <http://en.wikipedia.org/wiki/path_tracing> [3] Siggraph, Ray Tracing. Siggraph Juli 1999, [5 Mars 2010] <http://www.siggraph.org/education/materials/hypergraph/raytrace/rtrace0.htm> [4] Wikipedia, Bounding volume hierarchy, Wikipedia December 2009 [5 mars 2010] <http://en.wikipedia.org/wiki/bounding_volume_hierarchy> [Cassagnabére04] Cassagnabère, C., Rousselle, F., and Renaud, C. 2004. Path tracing using the AR350 processor. In Proceedings of the 2nd international Conference on Computer Graphics and interactive Techniques in Australasia and South East Asia(Singapore, June 15-18, 2004) [Jaroz08] Jarosz, W., Jensen, H. W., and Donner, C. 2008. Advanced global illumination using photon mapping. In ACM SIGGRAPH 2008 Classes (Los Angeles, California, August 11-15, 2008) [Moore91] A Moore, An introductory tutorial on kd-trees, University of Cambridge Computer Laboratory Technical Report No. 209, 1991 [Purcell05] Purcell, T. J., Buck, I., Mark, W. R., and Hanrahan, P. 2005. Ray tracing on programmable graphics hardware. In ACM SIGGRAPH 2005 Courses (Los Angeles, California, July 31 - August 04, 2005) 9