Kiirtejälitus

Kiirtejälituse juured ja tähendus

Enne kiirtejälituse arengut koosnes 3D-arvutigraafika põhiliselt "nippidest", mille kaudu üritati matkida objektide valgustatust. Kiirtejälitus oli esimene selle aja algoritm, millel oli ka füüsikaline alus.
Esimene kiirtejälitusmeetodit rakendav pilt arvutati välja Marylandi Ülikoolis aastal 1960. Väljaarvutatud pilt kuvati ostsilloskoobi ekraanil. Kiirtejälituse algoritmi peamisteks väljatöötajateks loetakse tihti Arthur Apple, Robert Goldstein ja Robert Nagel, kes selle algoritmi 1960. aastate lõpus avaldasid. Teised kiirtejälitusega tegelevad teadlased olid Herb Steinberg, Marty Cohen ja Eugen Troubetskoy.
Kiirtejälitus põhineb geomeetrilisel optikal, kus valgust käsitletakse kiirekimbuna. Kiirtejälituse käigus kasutatavad meetodid olid juba palju varem rakendust leidnud, näiteks läätsede tootmisel. Tänapäeval rakendavad paljud renderdid (arvutiprogrammid piltide loomiseks 3D-tseenide põhjal) kiirtejälitust, kombineerides seda vajaduse korral muude meetoditega.
Lihtsamad kiirtejälituse vormid võtavad arvesse vaid otsest valgustatust, st otse valgusallikalt langevat valgust. Pärast kiirtejälituse kasutuselevõttu arvutigraafikas on seda edasi arendatud. Täiuslikumad kiirtejälituse vormid võtavad arvutustes arvesse ka selle valguse, mis peegeldub muudelt objektidelt. Sel juhul saab rääkida mõistest "global illumination" (otsetõlkes 'globaalne valgustatus').
Kiirtejälituse ühte lihtsamat vormi kirjeldatakse ka mõistega "raycasting". Osaliselt võidakse neid kahte mõistet kasutada ka sünonüümidena.

Peidetud alade arvutamine

Kiirtejälitus on esmalt protsess, et määrata objektide nähtavus vaatleja suhtes. Selline põhimõte on üsna lihtne.
Kiirtejälitus töötab andmestruktuuriga, mida nimetatakse kiireks. Iga piksli jaoks arvutatakse välja kiire suund silma ja talle vastava pilditasandi punkti abil. Seejärel arvutatakse iga kiire jaoks välja lõikepunkt vaateväljas paiknevate primitiivide suhtes. Selle protsessi käigus arvutatakse välja ka objekti kaugus silmast. "Võitjaks" kuulutatakse lõikumispunkt, mis oli silmale kõige lähemal, ja ülejäänud lõikumispunktid klassifitseeritakse lähima objekti poolt varjatuks.
Meetod, mille käigus saadetakse silmpunktist välja kiiri, meenutab objektiivita kaamerat – see on nagu valguskindel kast, milles on väike auk. Kiirtejälituse käigus on aga augu ja filmi asukoht vahetuses. Sarnaselt kaameraga määrab ka kiirtejälituse puhul valgusava ja filmi vaheline kaugus fookuskauguse, mille põhjal stseeni töödeldakse.
Kuna kiired väljuvad silmast ja mitte valgusallikast, nagu looduses, räägitakse vahel ka backwards ray tracing'ust. Kiirtejälitus tegeleb küsimusega, kust valgus tuleb. Mõningates publikatsioonides on seda meetodit nimetatud ka eye ray tracing'uks või forward ray tracing'uks.

Lõikumispunkti väljaselgitamine

Eespool mainitud meetod keha ja kiire lõikumispunktide määramiseks on kiirtejälituse meetodi tuum. Lõikumispunkti väljaselgitamiseks kasutatavaid teste annab rakendada hulgaliselt erinevate geomeetriliste kujundite peal. Lisaks kolmnurkadele ja keradele on võimalik neid teste rakendada ka silindritel, kuupidel, punktpilvedel või isegi fraktalitel.
Kerade puhul on lõikumispunkti väljaarvutamine küllalt lihtne ja kiire protsess, mis selgitab konkreetse kujundi populaarsust kiirtejälitusel põhinevate renderdajate testpiltidel. Siiski lubavad paljud renderdajad tänapäeval primitiividena (baas ehitusjupid) vaid kolmnurkasid, millest vajalikke objekte kokku ehitatakse.
Uuemal ajal on olnud võimalik kasutada ka keerukamaid geomeetrilisi põhimõtteid, näiteks NURBS-i. Eeliseks on suurendatud täpsus, kuna pinnad ei koosne vaid kolmnurkadest. Tagajärjeks on samas pikemad töötlusajad, kuna lõikumispunkte on vaja arvutada keerukate valemitega. NURBS-ile omast täpsust on küll võimalik saavutada ka kolmnurkadega, samas nõuab see aga väga suure hulga kolmnurkade käsitlemist, mis omakorda pikendab töötlusaega.

Varjutamine

Lähima primitiivi määramise protsessi käigus leitakse lisaks lõikepunktile ja kaugusele silmast ka primitiivi pinnanormaal. Nõnda on olemas vajalik informatsioon, et määrata silmpunkti peegelduva "valguskiire" värv. Selle käigus kasutatakse ka stseenis paiknevate valgusallikate kirjeldatud omadusi. Kõik arvutused põhinevad lokaalse valguse mudelil, mis on võimeline simuleerima materjalide olemust. Seda pilditöötluse osa, mis tegeleb värviedastusega, nimetatakse varjutajaks.

Näitekood

Lihtsama kiirtejälitusel põhineva programmi loomine ei ole kuigi töömahukas. Pseudokoodis saab vajalikke põhimõtteid kirjeldada nii:
Funktsioon Pildi_töötlemine
   Kiir.Allikas = Silmpunkt
   For every (x,y)-Rastergraafika pikslid
       Kiir.suund = [Pilditasandil asuva punkti 3D-koordinaadid] − Silmpunkt
       Värv (x,y)-Pixel = Värv_suunast(kiir)
Funktsioon Värv_suunast(kiir)
   Lõikepunkt := Lähim_lõikepunkt(kiir)
   If Lõikepunkt.võitja = (False):
       Värv_suunast := Värv_taust
   Else:
       Värv_suunast := Värv_lõikepunktist(kiir, lõikepunkt)
Funktsioon Lähim_lõikepunkt(kiir)
   MaxKaugus := ∞
   Lõikepunkt.võitja := (False)
   For every primitiiv steenis
       Lõikepunkt := Testi_primitivi(primitiv, kiir)
       If Lõikepunkt.kaugus < MaxKaugus :
           MaxKaugus := Lõikepunkt.kaugus
           Lõikepunkt.võitja := Primitiv
   Lähim_lõikepunkt := lõikepunkt
Iga kiirtejälitaja, ükskõik millist kiirtejälgimisega seotud meetodit rakendades, jälgib sarnast struktuuri, mis sisaldavad veel lõikepunktidest (Testi_primitivi) ja varjutajat (Värv_Lõikepunktis).

Kiirendusmeetodid

Esimese kiirt tabava primitiivi määramiseks võib, nagu ülevaltoodud näitekoodis, testida kiirt iga stseenis oleva primitiivi suhtes. Samas pole see enamasti vajalik, kui on teada, et osad primitiivid ei paikne kiire läheduses ja seega on võimatu, et nad kiirega pihta saavad. Lõikepunktide väljaarvutamiseks on kiirtejälituse meetodi puhul töötluse kõige aeganõudvam protsess ja seetõttu on tähtis arvutustesse kaasata nii vähe primitiive, kui võimalik, et säästa arvutusaega.
Kiirendusmeetodite käigus jaotatakse stseen mingite süsteemide järgi automaatselt alamtükkideks. Nendesse alamtükkidesse grupeeritakse sealpaiknevad primitiivid. Kui kiir saadetakse stseeni läbima, ei arvutata tema lõikumist kogu stseeni suhtes, vaid hoopis alamtükkide suhtes, mida ta läbib. Nõnda peab lõikumispunktide arvutustesse kaasama vaid alamtükkides paiknevad primitiivid ja mitte kogu stseeni informatsioon.
Kiirtejälituse jaoks on välja arendatud mitmeid selliseid kiirendusmeetodeid. Näited alajaotussüsteemidest on näiteks vokselvõrgustik, BSP-puud ja bounding volumes, mis primitiive ümbritsevad ja stseeni osadeks jagavad. Samuti on võimalik eespool mainitud meetodeid kombineerida. Animatsioonide jaoks on välja töötatud sarnaseid kiirendusmeetodeid.
Ükski kiirendusmeetod pole universaalselt optimaalne. Efektiivsusaste sõltub suurel määral siiski stseenist. Samas vähendavad kiirendusmeetodid stseeni üleüldist töötlusaega väga suurel määral ja võimaldavad kiirtejälitus algoritmi praktiliselt rakendada. K-dimensioonilistel puudel baseeruvad kiirendusmeetodid on enamus mitteanimeeritud stseenide jaoks üks efektiivsemaid tehnikaid, kuna seda on heuristikat kasutades veelgi optimeerimisvõimalusi. On ka kindlaks tehtud, et stseeni ajaline keerukus on logaritmilises sõltuvuses temas paiknevate primitiivide hulgaga.
On näidatud, et tänapäevaste arvutite puhul pole kiirtejälituse pudelikaelaks mitte protsessor, vaid hoopis mälule ligipääsu kiirus. Vahemälu hoolika majandamise abil on võimalik algoritmi märgatavalt kiirendada. Samuti saab kasutada protsessorite SIMD-arhitektuuri, mis võimaldab paralleelseid arvutusi ning spetsiaalselt optimeeritud eraldusskeeme. Sedasi on võimalik üheaegselt jälgida mitmeid "pakettidesse" kokkuseotud kiirepuntraid. Seda põhjusel, et enamus silmpunktist väljasaadetud kiiri on üksteisele väga sarnased ja nad tabavad tihti sama objekti. SSE käsustikega saadakse korraga testida nelja kiire lõikumist objekti suhtes. Spetsiaalsete riistvaralahendustega on võimalik ka suuremaid, üle 1000 kiirt sisaldavaid pakette, jälgida. Kahjuks kaotavad vahemälu- ja SIMD-optimeeringud enda ajaeelise komplitseeritumate kiirtejälitusmeetodite kasutamisel.
Veel on võimalik kogu kiirtejälitus protsess paralleliseerida. Selle realiseerimine on küllalt lihtne, kui anda konkreetsele protsessorile/arvutile pildi erinevaid juppe töötlemiseks. Paralleliseerimisega toimetulekuks on vaja vaid mõningaid optimeerimismeetodeid kohandada.

Mälutarve

Kiirtejälituse protsess ise palju mälu ei tarvita. Küll aga hõivab palju mälu hoopis stseen – keerukamad stseenid võivad koosneda miljonitest primitiividest, mille maht võib ulatuda gigabaitideni. Lisaks sellele peab arvesse võtma ka kiirendusmeetodite mäluvajadust. Kuna väga suured stseenid korraga arvuti mällu ei mahu, on vajalik lehekülgede saalimine.
Suuremate ja keerukamate objektide puhul, mis esinevad stseenis mitmekordselt ja erinevad vaid positsiooni ja suuruse poolest (näiteks mets), pole kogu geomeetriat vaja korduvalt mällu salvestada. Läbi eksemplaarimise (inglise keeles instancing) on võimalik kokku hoida palju salvestusruumi, kuna objekt laaditakse mällu vaid üks kord.

Edasiarendused

Üks kiirtejälituse meetodi edukuse põhjuseid on tema edasiarenduspotentsiaali rohkus. Eelpoolkirjeldatud algeline metoodika pildisünteesi jaoks ei ole enam tänapäevastele nõudlustele vastav. Tõusva arvutusvõimsuse ja füüsikast ammutatud inspiratsiooni abil (esmalt optika ja radiomeetria) on loodud mitmeid edasiarendusi ja variatsioone, millest mõned siis lühidalt kirjeldatud on.
Üleüldiselt kehtib, et iga edasiarendusega tõuseb võimalik kvaliteet, aga ka vajaminev ajakulu, mis path tracing'uga oma maksimumi saavutas. Alles hiljem seati arenduses siht protsessi ajavajaduste vähendamiseks ilma, et kvaliteet selle käigus langeks.

Vari

Kiirtejälitusalgoritmi paindlikkuse tõttu on võimalik valguskiiri lisaks silmpunktile välja saata ka ruumi muudest punktidest. Seda demonstreeris 1968. aastal Arthur Apple ja näitas, et seda meetodit saab rakendada varjude simuleerimiseks.
Pinna suvaline punkt asub just siis varjus, kui tema ja valgusallika vahel objekt paikneb. Seda saab kindlaks teha, kui saata silmast tulnud kiire lõikepunktist välja kiir valgusallikasse et näha, kas uus väljasaadetud kiir mingi objektiga lõikub. Kui nõnda juhtub, asub lõikepunkt varjus ning silmpunkti kiire heleduseks määratakse 0. Vastasel juhul leiab aset tavaline varjutamine.

Rekursiivne kiirtejälitus

Kiirtejälitust saab rakendad lihtsatele, valgust mitteläbilaskvate, kehadele ka läbipaistvatele ja peegelduvate kehadele. Sellel puhul saadetakse lõikepunktist välja uusi valguskiiri. Peegelduvate pindade puhul on vaja välja arvutada peegeldumisseaduste põhjal uue kiire suund ning välja saata vastav peegelduskiir.
Valgust läbilaskvate objektide puhul saadetakse välja kiir vastavalt Snelli-Descartesi seadusele, seekord objekti sisse. Üldiselt peegeldavad läbipaistvad objektid osa valgusest tagasi. Murdunud ja peegeldunud valguse värve annab arvutada Fresneli valemitega. Selliseid kiiri nimetatakse sekundaarkiirteks.
Kuna sekundaarkiired võivad tabada ka muid objekte, kutsutakse esile algoritm rekursiivselt, et võimaldada mitmekordne valguse peegeldumine ja valguse murdumine. Kogu protsessi hierarhilist ülesehitust kutsutakse ka töötluspuuks (inglise keeles render-tree).
Rekursiivse kiirtejälituse töötasid välja Kay ja Whitted 1980. aastatel.
Rekursiivse kiirtejälituse puhul näeb pseudokoodis kirjutatud varjuti välja nii:
Funktsioon Värv_Lõikepunktis(Kiir, Lõikepunkt)
   If Lõikepunkt.Võitja.Materjal = peegelduv or läbipaistev
       Peegeldav_Osa := Fresnel(Kiir, Lõikepunkt)
       Värv := Peegeldav_Osa × Värv_Suunast(Peegeldumiskiir)
              + Murdunud_Osa × Värv_Suunast(Murdumiskiir)
   Else:
       Värv := 0
       For every Valgusallikas
           Varjukiir := Valgusallikas.Positsioon – Lõikepunkt.Positsioon
           VarjuLõikepunkt := Lähim_Lõikepunkt(Varjukiir)
           If VarjuLõikepunkt.Võitja = Valgusallikas
               Värv := Värv + Otsene_Valgustus(Kiir, Valgusallikas)
   Värv_Lõikepunktis := Värv
Ülejäänud programmi osad võivad jääda samaks, nagu nad lihtsa kiirtejälituse puhul olid. Siin näidatud funktsioon Värv_Suunast võib esile kutsuda funktsiooni Värv_Lõikepunktis, millega tuleb esile funktsiooni rekursiivne olemus.

Difuusne kiirtejälitus

Rekursiivne kiirtejälitus võimaldab lisaks valguse murdumisele ja valguse peegeldumisele ka teravate varjude simulatsiooni. Reaalsuses on siiski valgusallikatel olemas mõõtmed, mis varjud pehmeks ja uduseks muudavad.
See efekt, nagu ka sakitõrje (inglise keeles antialiasing), läikivad peegeldused, jne. lasevad ennast difuusse kiirtejälitusega (inglise keeles distributed ray tracing) abil simuleerida. Selle kohta publitseeris von Cook aastal 1984 paberi. Meetodi idee seisneb ühe kiire asemel mitme kiire väljasaatmises ning nende kiirte värviinformatsiooni keskmise väljaarvutamises. Nõnda on võimalik luua näiteks pehmeid varje. Protsessi miinuseks on müra, mis tekib, kui liiga vähe kiiri välja saadetakse. On siiski olemas meetodeid, nt importance sampling, mis müra vähendab.

Path tracing ja light tracing

Difuusne kiirtejälitus võimaldab küll simuleerida paljusid efekte, kuid see ei ole võimeline simuleerima globaalset valgustatust koos efektidega, näiteks difuusne interreflektsioon ja kaustikefektid (läbi valguskiirte koondamise tekkivad valged valguslaigud). See on põhjustatud tõsiasjast, et difuusse kiirtejälituse puhul tekivad sekundaarsed kiired vaid valguse peegeldumise ja murdumise korral, mitte aga difuussete objektidega kokkupuutel.
Aastal 1986 avalikustatud publikatsioonis kirjeldas James Kajiya töötlemisvõrrandit, mis lõi matemaatilise aluse globaalsele valgustatusele.  Ühe kiire "heledus" defineeritakse nõnda radiomeetriliselt korrektselt kui kiiretihedust. Kaijya näitas, et globaalse valgustuse jaoks peab iga pind välja saatma sekundaarseid kiiri. Lisaks näitas ta, et render-tree ei tööta piisavalt efektiivselt, kuna palju tööressurssi kulub suurtes hierarhiasügavustes arvutamise peale, ning on parem, kui välja saadetakse vaid üks kiir. Seda meetodit tuntakse tänapäeval nimetusega path tracing, kuna valguskiir otsib endale silmpunktist teed läbi stseeni. Path tracing'ul on matemaatiliselt ja füüsikaliselt paindumatu struktuur.
Kui path tracing'u käigus difuusse pinna poolt välja saadetud sekundaarkiir tabab valgusallikat otse, ignoreeritakse selle heledusosa. Heledusastet arvutatakse hoopis varjukiirte põhjal. Alternatiivselt võidakse otsest valgustatust arvutada nii, et välja saadetakse vaid üks sekundaarkiir, ja kui see tabab valgusallikat, tagastatakse tolle valgustihedus. Kumb kahest mudelist efektiivsem on sõltub pinna lokaalsest valgusmudelist ja jälgitava objekti nurgast valgusallika suhtes.  Eksisteerib ka kontseptuaalselt lihtsama path tracing'u variant adjoint photon tracing, kus varjukiiri välja ei saadeta.
Kuigi path tracing on võimeline simuleerima globaalset valgustust, väheneb tolle efektiivsus väikeste valgusallikate puhul. Selle all kannatab eriti kaustik ja tolle peegeldused, kuna välja saadetakse väga vähe kiiri. Seetõttu kasutatakse tihti teisi, path tracing'ul põhinevaid meetodeid või edasiarendusi.
Light ray tracing on haruldane versioon kiirtejälitusest, kus selle asemel, et valguskiiri silmast välja saata, saadetakse kiired välja valgusallikast. Pikslid, mida pilditasandil tabatakse, värvitakse vastavalt kiire omadustele. Nõnda on võimalik täpselt simuleerida kaustikaid aga teiste efektide simuleerimine kannatab ebaefektiivsuse all, kuna paljud kiired pilditasandit lihtsalt ei taba.