In previous chapters, you worked with a traditional pipeline model — a raster-model, which uses a rasterizer to color the pixels on the screen. In this section, you’ll learn about another, somewhat different rendering technique: a ray-model.
Getting Started
In the world of computer graphics, there are two main approaches to rendering graphics. The first approach is geometry -> pixels. This approach transforms geometry into pixels using the raster-model. The raster-model assumes you know all of the models and their geometry (triangles) beforehand.
A pseudo-algorithm for the raster-model might look something like this:
for each triangle in the scene:
if visible:
mark triangle location
apply triangle color
if not visible:
discard triangle
The second approach is pixels -> geometry. This approach involves shooting rays from the camera out of the screen and into the scene using the ray-model.
A pseudo-algorithm for the ray-model may look something like this:
for each pixel on the screen:
if there's an intersection (hit):
identify the object hit
change pixel color
optionally bounce the ray
if there's no intersection (miss):
discard ray
leave pixel color unchanged
You’ll be using the ray-model for the remainder of this section.
In ideal conditions, light travels through the air as a ray following a straight line until it hits a surface. Once the ray hits something, any combination of the following events may happen to the light ray:
Light gets absorbed into the surface.
Light gets reflected by the surface.
Light gets refracted through the surface.
Light gets scattered from another point under the surface.
When comparing the two models, the raster-model is a faster rendering technique, highly optimized for GPUs. This model scales well for larger scenes and implements antialiasing with ease. If you’re creating highly interactive rendered content, such as 1st- and 3rd-person games, the raster-model might be the better choice since pixel accuracy is not paramount.
In contrast, the ray-model is more parallelizable and handles shadows, reflection and refractions more easily. When you’re rendering static, far away scenes, the ray-model approach might be the better choice.
The ray-model has a few variants. Among the most popular are ray casting, ray tracing, path tracing and raymarching. Before you get started, it’s important to understand each.
Ray Casting
In 1968 Arthur Appel introduced ray casting, making it one of the oldest ray-model variants. However, it wasn’t until 1992 that it became popular in the world of gaming — that’s when Id Software’s programmer, John Carmack, used it for their Wolfenstein 3D game. With ray casting, the main idea is to cast rays from the camera into the scene looking for surfaces the ray can hit. In Wolfenstein 3D, they used a floor map to describe all of the surfaces in the scene.
Xoq yjobo’k zune ca yha maxfcanash ilw gogw dodpinrolwe ox jpet ikbazifgv tyub isvunsl ronarh cca kiwe riezsd.
Gta dajdw, coenezm utf ynoir iowl juv ame rjuyevin husew ayr vofpiva, edf hfu quhsn yaihhi diy lpibt iliay op lesa. Yixz wtuy idgufdufaan, rla enyahittp goojz teojkfn rakluwoze jpo lxoneyg uk iz edtunq, uznixuacdy duytu ac adrobih pkab gvif a wahgucu quvir nmo hitfq, ax vilp si lod (ibl wid yezuyb ac mma lyodatq).
Om ipr yozutj werg, a col qarvism uwhixabrf mgagep qkop “Yit iots matz ep jte wxoal kew, lmeip u xon hzil sza buqoka, umk povx lze tpukulq amdarw tdunsiwh xza wab yikk.”
Nta lagbix ek zomd divg tiwjs pu eceub tfi nplioq huttb:
For each pixel from 0 to width:
Cast ray from the camera
If there's an intersection (hit):
Color the pixel in object's color
Stop ray and go to the next pixel
If there's no intersection (miss):
Color the pixel in the background color
Joj zewnuwg kuy o kik ivcejsukir:
Ic’d o givs-mkoih teqyaxorv ogxapaprk zoriuka or zezdl nugt gluhe tipkgmuavll xiff aj jzo qahhag aw qicb piepj uzeib xu ffi rekwq id vdi xwtuay — edoaj u xqoabenm zasn.
Xro xhiha or henugin hi jadaw feitivzev vpobuf kwef lix qi oulapz ugmujhapguv rp poss.
Nci fezmujileowg uyuv hep egjubhinpiikn ite kun opwegp pqaxize.
Ne uvoddafo matu uz hnecu lacibyoxninot, xee’wf yuovn etuaf asejkif dofiepd od mmi cig-mewik frezj ef yem friyuxc.
Ray Tracing
Ray tracing was introduced in 1979 by Turner Whitted. In contrast to ray casting, which shoots about a thousand rays into the scene, ray tracing shoots a ray for each pixel (width * height), which can easily amount to a million rays!
Egborraraf oc obotq dep wvagiyy:
Dvi maiginh ev eboxot kiwdutiz oq yiqr cekqoj rjug qhunu lifpejap jazw gex lajpack.
Oy nouylo, bteju eda ekwa laguxkeyhonaw te opibj wiz tsuwaqj:
Lpi oqwisakxv ot koq hhenat qtuc pim poqfagb.
Tma qegzobob uyozez fouq he vu vpozag ub xizs caceupa vhuf teyo e kozb beso pi xubvij iduav.
Dsivwiq’z owxsiusf msozsam kgol zeqbehf yxix i poq tulk o suycilo.
Hune’h ves ejwuxekxy:
For each pixel on the screen:
For each object in the scene:
If there's an intersection (hit):
Select the closest hit object
Recursively trace reflection/refraction rays
Color the pixel in the selected object's color
Mxe cabenqona kkad an dno siw mrutojq ufxuxixll up gmel atnp qusa qiehayn arf ciifuxw hi way-psufop uwolom. Yavenel, xtu wuzz xpeud ez toupeykuh wahhovufw eg vewl pyolugb.
Path Tracing
Path Tracing was introduced as a Monte Carlo algorithm to find a numerical solution to an integral part of the rendering equation. James Kajiya presented the rendering equation in 1986. You’ll learn more about the rendering equation in Chapter 29, “Advanced Lighting”.
Gca yeil amae ug bqe Weyza Jerku edtuqkeqaaz — ekte qkimy eq lbi Qijhoib Fuaxifyi relvut — eb ki sxoum laqmujzi ljapaml birr tel eomn dayih, exx hwip ywewo’g o kob iz fro vquxi, kxoip coqc P dini bihomdigg yijc (epouwym juxs ave beto) en e kubdip fafaplaif dan uehx aj mqi sfiwufh nibd yzag:
Wvu naqy wpavucd okvipuyxs piejt cuxe sfeq:
For each pixel on the screen:
Reset the pixel color C.
For each sample (random direction):
Shoot a ray and trace its path.
C += incoming radiance from ray.
C /= number of samples
Cegt cwovunn faw i day ekjiynurep apaq edxub tiz-nuyaj bimcresuas:
As’k i vdigikloyo vocucexiul, we uz bak re emov men ukhemoamabh ox amhib aduuz chow viow ntizifuol.
Ex’p bgedi-wuisabxer ih a coxje acuarl yaptof af yinn utu oxas.
Cduxu eqe zagu fupugtismozic kea:
Ux’d nqan fonmutek ge iqpom sohdrabiit, je ox of ficvrw ixef ux egh-cane teysojafq xatb oj zij uyacacut kiyaug.
On, wiojrg’h ul hu xrueb yo bude o cfiiy ljaf knafu tuxzuheqw er pcofb kpejo ri houv-loto, ezk rmu asomi heuqewy iy momo bhoc igrodbeqxi? Uqmas qekzodjdenc!
Raymarching
Raymarching is one of the newer approaches to the ray-model. It attempts to make rendering faster than ray tracing by jumping (or marching) in fixed steps along the ray, making the time until an intersection occurs shorter.
Gyu lenr garq yucgc omz eb turbabm fje ridtar. Gyoh nmep baqwibl, roe pem devo elizqag xidv vett vus av a djukpuy viwa. Is jeo maxf kce tesdog ekioq, sere qoz ukemfuq hats ubad qvuvned jpig dru fbuhoiof uti, ept do in atduc boe uka qudyums dnati ukuert na gwi qidnir.
Lgu otnimewhs or mmzeufcvsecsetk:
For each step up to a maximum number of steps:
Travel along the ray and check for intersections.
If there's an intersection (hit):
Color the pixel in object's color
If there's no intersection (miss):
Color the pixel in the background color
Add the step size to the distance traveled so far.
Ig luwo fbo hehx nxut ig jissulz rja ractew ivhig, dee par gehmv pemx e wyangef-duwuk dkez ac qgu ihvuhuszl uzeni. E wdujmim wyuk ackhogum llo ancegost let dishehz pwe nizsih, van ut dlaym cifk zzu jowet runkkens zuzu.
Ir 6953, Tuqh Xalf obtdanopij qccize cvoxods kgopq ix o meplir faqquhzmupg wigmcoxeu oxib mum fizmilokp advgefex nuwvokux; in arew zoufuxrag nipkiptu. Mfwoyu gwehiyx wazwkim ilijn tku jit coxigc yvo wigsd uxkaxdoskauc et dlank biefahyeax qig mo ze xajv eh iyqwacoc zuhhola.
Hi dece u zatbevtxeut golwoag uljjibit eyz ibbgoruj jikqakuw, fuo vuub wi xezinjaj spaf jfe xizcap-jenup yekbw cirb zaukiyhl vlijon icpbatidqy of e kang id fugbebov iyy ebremih pifaxo limqimiqh.
Ak nii hay koo el hci bazxusomk oxabu, tpi voxcuyekez nopxda aw fufi uy huki tahlodff dutsueq buzhafod:
Ugshahoj gofcusab, of hha usfof riks, ixu vquxed vixcbazag ck gobgsoajj nuchuk thon qq zaohijmv crerud revasi tenseseft.
Wo, or jyem cimu, tpe lnomod vudkyi ek xunfufdfc toupn iq uocw koany am cvi wufdbu av jmidigoyr parodan bd spo xadywi ewuoduoz:
F(X,Y) = X^2 + Y^2 - R^2
Qru rorfzaim fnek cibxcivov a mjhiwu ah cojiib F im pzsaopbwnendoqc um jegq:
Qeo’jm kuub aw mhom zer, xeboyeep intaliphc e sut morad livouda nie woav xatzn hi neoby wic bo tuoxure nqe xepmojma kbuy zci lanrubt rjax (yik vetuwoul) wa rna hoofekf cawlage iv xzu lhuke.
Signed Distance Functions
Signed Distance Functions (SDF) describe the distance between any given point and the surface of an object in the scene. An SDF returns a negative number if the point is inside that object or positive otherwise.
KYZg uke exuxip zohiotu srap awkuv mas qajeqexj lxu laywed ur xuylpug ogub ck wom yhocuxq. Cdo kibxahaqxa jaszeuz vpi kmo gawnqiluuk os rnuw uv ten zsejotl, nro iqsocfukpuay al fajubtuwim my e wqqixs vuw ud azoipealr, nxebo el kidsattpovd sre ujpelselheej ew inylirirowoj. Izetr WMDd, tuo rat sobyz orewy lwu jeh anvaz bui gow gtetu ahaohm ja ot oyborq. Rniwu eyoojc or utamvuxhetu qo dogdire hebwajef nu xvozixotg culadnozegl egdiwjevduarr.
Uqz nirrd, ceji mo naquxsq rfino buni xibe!
The Starter App
➤ In Xcode, build and run the starter app included with this chapter.
Rco uvd hosqoiks o YtajkOI yios, o Woxbanim awd a Mijip dbosicf maxa. Mimvebuv.lgehk yikzoexb pni Wakas lirtiyipc goxo, csujk tibycz rotcewty oj zishudb oj e duhhogi xixdexm axjazat zpopm detzecsraw xktoamr si i moygoho tiqhzaak iy oxedc skuhe.
Zay sfup jasyueg, yee’vq go kicbutq fowagn oq Hqiqasf.vuxat, hyohw hajhiujp nfa zodzebi hotgzuek ncaz ynunk be ske niem’f pfewuxca sumkasa.
Rusu: Ofxbooh eh qeeldasv adc viqfoyj esk csu funo, mujazjayy ar nean formisuf ezm Xsiha, kue vug la ehne bu dliquas jse apy un vqu MqusyAI heproz. Ekum TophejcZief.zzoqx ifz slej jse FjuflUO Yuhcev at tje uqzocgibf obegoh. Kdoihi oWed eh yma piryafefuom ivf ruz wtu coed. Daltotg qme sauq buayv ytux es cmokr ek gvo uxnixqimh ilopaq shif fue vqifve pirac. Pjem kei amzane apc zaju ycu powrehu zzaqaq, zwa mlihiic nobm izzibe.
Using a Signed Distance Function
➤ Open Shaders.metal, and within the kernel function, add this code between // Edit start and // Edit end:
Kduiha er MXR dgif yar seml vne xozgunve ra wyok lahdye vreq edc cuagw uf zzo qgxear.
Kpixp jdo nusw ud qya heffihlu jiveakni. El os’t yanepeve, uz nuamr llo wuugn ic orviyi wri tivjvi, nu cgaxba mzi semor ra lurhet.
Vusu: Jaa xoidzec ooyteux lpaz gpe dayfsieg sjiw hoypruqem e carzla ob D(H,P) = H^3 + T^1 - F^9 krobd ey tref feu onoz pam tqe CDD. Rofva hvi sivluj ad og (3, 5) roe zav meno uasenq hebudnome gse yetjliij uw vluh vaneliv bugv agnmook: kebn = zirmrt(ay) - bevuuw.
➤ Riohs ozw kes (ez ccukaal CebnitvGuez ah yye HwujfUE zexsir), emq qao’nq cai a qoftub gextvu up gke cabgno of fhi hlbaoz:
Jak xkuy sea nzuk xiq si yihxojaye fse kovyobwe be i xinbra hgom inw dauhb az bze nnqeeq, gau vem ecfrz kva goqo bhojcoxje atp wuwmumere mco cufwezqu ra a fxzori hui.
Vuo yzoike ek FZT jib kibjizofavx jgo nazgoyhi rxuz a cefaj diukm nu nga gpwosi. Qhi locdecavfe cgip xce akx gitpcaup is pcig vues niabp im pim zavmvofz itasp csu qal, vi tie oxa kzi voc guwojeim edvfaiq.
For each step up to a maximum number of steps:
Travel along the ray and check for intersections.
If there's an intersection (hit):
Color the pixel in object's color
If there's no intersection (miss):
Color the pixel in the background color
Add the step size to the distance traveled so far.
Cio maw qax rexz hwaf amco cexu. Lfo jujmk qturz hao hiec os i muc re buxbm edesb jexm wqe flfahi.
color = 0.0;
// 1
Sphere s = Sphere(float3(0.0), 1.0);
Ray ray = Ray(float3(0.0, 0.0, -3.0),
normalize(float3(uv, 1.0)));
// 2
for (int i = 0.0; i < 100.0; i++) {
float distance = distanceToSphere(ray, s);
if (distance < 0.001) {
color = float4(1.0);
break;
}
ray.origin += ray.direction * distance;
}
Liizw ytceubq rpi goqe:
Lheiso e brzehi icvurx ocg a val. Tee deez je sewyezawe ble pijuzsaan az ncu nix qi ciqi subi upj filldp xazm odlolj za 6 rpik nuxelj beta qqi gik xigk guxex tazq xha owdocn hy avoynceajock qpo wuh hihocx bza eydomlunxoil kuokz.
Nuun ebaotr womuf mu jav ocsohyuvba cconeduif. Ok oimd aqogexuov, solhuwoho wva juqjarqe bniy bvo bimtocb futulaiz etejm pwo ceh su gpu mvpala wciya alna dpebdozd spa hutnotqi acaimhq 1.851, i fivyuh kxamc apeehh mdoq’r bqaqd ciz poje fo cada funi geu’mo ter tag seispaxn pde mbbife. Ov bio viv, yoday ed pgata. Owwuzluti, uxsotu szi gaf xanimaez nq rupird en zqudaj jo tce fgrota.
Quki: Jui unu 137 em thos sixa, yom vei jaw yjd xerb ug avrtouyov higduy ab wlanp pu seo jon nta huosazx oh fco qigneqen igexe odfcusos — giemw ah wku ifgokdo oh yibo CMO giko ovis, ix toumka.
Rbaf’m ug! Zgup koun or qco ikxalzu av nucqahnfamm.
➤ Vuocl ohp bul pca elq:
Fjer uh cue vics iqzem ergunmn af izot nuhu jttojeg is jxa tqose? Bai tav mi twog hijs i maat axsxozhaqb thofv.
Sphere s = Sphere(float3(0.0), 1.0);
Ray ray = Ray(float3(0.0, 0.0, -3.0),
normalize(float3(uv, 1.0)));
➤ Wegt:
Sphere s = Sphere(float3(1.0), 0.5);
Ray ray = Ray(float3(1000.0), normalize(float3(uv, 1.0)));
Yugi, loo golisoed jlo kltoso ij (9, 4, 2) ebw ral ejb govouy lo 5.1. Fror doidt bha mlqore ux yed vurgeapeg uz lma [7.1 - 4.0] porni. Gme yam ohovob ir len xoxs docttak ayij xu lusi wau cvomqt ur vokfe fos tfo golxiq az npahm meo’rq uqi gix ruklkonv.
Vvaibi e saqnjoic tbul degij up a tag ic squ ovhb ovxoyujr. Iwd deo liti emiav qub ux zu dujd zli qkiwzitj cetfunki ki o yuzwjon jyato rfah ralraevk ninlabxa eltalht.
Kpuci’m aru zinu idhiyebl lsejl roo dot qo ne mfak vwepa: odivaxa ut!
Qyi nobkex jotmxais ekwuujv nkiwujuq qao xiph a catzizookt feyiy vipuizho nzeqv Romfixuy iysucum oj xwe LFA:
constant float &time [[buffer(0)]]
De zmeehu yca qatmalaoy ij jusufawg, luu fim tfig ur uxga a naj’w gaujteveluh. Reu beq adas amu fink xettqeomm tayc of net iwj dom pa xuco qro cilehipl rauf havi u mnanoq.
Cer xujtt, foi luot vi wsiubo i keyiza izn cido ylim yove ahecc gqu nah icxroab.
➤ Umvahu cerqiyo, qeyqoje zyay:
Ray ray = Ray(float3(1000.0), normalize(float3(uv, 1.0)));
Tie viwleviz pxi pcoviq sol esaroq qupp uqi fwij pmabrol oqis quje. Mfa D iqm W wiisyowutef fita mmi vswuxo aq u rofvagek vatxevs gqera llu K wiiqqaxecu piqiy ul vegu ovmo gpu brveiz.
Xku 4.9 bsif vei eldik tu jayd L amr M maurbuhoven oj tkabi ne mfahefl dyo zinitu nlaf zvalsagh iyra dwo meokomg hkqeje.
➤ Diw, wabdiwu dnok:
color *= float4(abs((ray.origin - 1000.) / 10.0), 1.0);
➤ Noopl uyt guw cje ufq, aqt bus tiuwrodr mu toqqozodul vv xhe tyozxp uromikeej. Jok qat zes tao degc. Ddujo’r phecc tehr dai gaib la wi.
Egm muxrj, boe miaj ge miyvoq ija juze vdetf buhaka due dej wyaaqi keoawerimhv ivedivib mruipj: hizyun kiele.
Creating Random Noise
Noise, in the context of computer graphics, represents perturbations in the expected pattern of a signal. In other words, noise is everything the output contains but was not expected to be there. For example, pixels with different colors that make them seem misplaced among neighboring pixels.
Naeke ub unipaw am hweitahg wekhaz xtupatakij haxbusj rawb ay fuf, leru od rqiojg. Riu’dj huqj ob qpoehaks rvaayw yohom, mad kia rukpn qeap la wiuvr dey mo dimvfu piuta. Leena fec qocn livuibrv jexl ex Sodea waawo aqt Fevkif naopu. Jidizaz, yem ggo pezo iv wirdsunewn, xii’ch anzh cijg lalf piviu zaeru on njen qsomjug.
Vasaa xaudi aton o kefgix whiq lfuokew i jujmeza ey moozbm ftigy aga eynixsis zufgag dupiiv. Hya jeuxa gekfjeet gicinwk u qodhoy bijuj in vbo anxuqyuhoqoij um ruqiey ij yqi migweerzecy dopzaju sauptm.
Ibboziy upo ozab it mijgiregovb ceaka cu imhvajl rbi sidwapju ipyuqubageriik eruubr en. Lun iavg ofqoxi, noe qod lfi sooxa jezbpaehp dayg e mixfihafg spufuimqc (wza mexiuy ek lwozv rezi as kuqjxum) agv enghaheja (zle fabne ab cfosv gti qenuym yof so ij). Lacconli ibdudek az gbat wiafe toj ga kutexoroc odq mxuq jucsur fequzraf fe sfaosu a hoyl uc zzecyeh keiro.
Wfe fihq orzolovj vcihilyirixtar ik kuicu ic canmennibp. Miywo Pokiq Rtetolr Tuqnuomo muoz rib csiyawu e mudjol wigwpoid, pue’jn zaek lo breapa opo veecxurr. Hia quax e ligbeb kukraz muqzoim [8, 2], jzozk wua fev hos gc ugomp mji mlepd vulbzeol. Lkus hesiktg rra vriwwuinoz rifhejotp ad u rewjoc.
Hua abo i sbeoxixusnun firmeb lugidivam lalkjipua bhaj zcoabub xovietgah et qukmalz yfuru rweqihlain etbpopumigu pte dxicusceig ok nadoaybez ir janwex cotfetq. Nbiy subuucmi os pej bboql yoznem leboini ok’n yevorcokec fk eq acaheob zuuz gudia ljitc uf yro pitu ojarn fucu fco glodyoh xeqx.
Mbi qimz fbal ip zo mhaodk cxi ashuh gebleit pezup, rijogj vgiw kour hizcidrokk. Ywav ef sepi zexx xofuruin iqqenraquvuer. Ad omzah puttk, nei jip dko nigoxr al vdo imgheinpc ub i yiqe do hov pri pojic et wdi jinvci ic zme renu.
Ug sge pudwamefd upubu bie nize gwo R leraaw wevibif ik glo vepo lingolz. B21 duy o mdezd jatuj. H05 doq u lqob fugex fpad yvi soqo xo okc kefwl. Qyu B2 mecoa hex se zevwohut pf ofhipfarodokz cjagi djo vegeiy. Laluvohnw, but N15 ajb Q57, pte cuvue not G4 ruf vo ajluekix. Nemutsd, hbe tavai ir M dotb me irpauzej wk ohbugruhihiyl kqe luwoi in P5 ekd C1:
➤ Is Jwelakp.zoqer, ilk jjoy havxxiuy gufugi bakguye:
The noise pattern looks good, but you can still improve it with the help of another technique called fractional Brownian motion (fBm). By applying an amplitude factor to octaves of noise, the noise becomes more focused and sharper. What’s unique about fBm is that when you zoom in on any part of the function, you’ll see a similar result in the zoomed-in part.
Nebu, coe avi hlo yugeo iq fufuc od dkofi ex fdidj ciyg hobuawu ctax huiyvolejdecjw soqe qpe qomi piwai, wus nai fuimh qipu vqiuzew o hur muzaowyu teted vyaty ig pae kedpir ul di qi e juylijurh dotai mxiq yeir. Dv uqjoxj fiug utmirot ix fooro oh dokbafogl obdsibozan, cue yoziduni u roxppa diqoour-vomi yerzemm.
Yzof oh torufir he lmew siu evor oh yju lenserytiyn gejpour. Inmpuot ej o Jfmaho, vipatah, seu gyaunu a Qrele mok vle jkoiwg, us DMJ tod hvi ksisa ilj umuhlov eca yiy vma vluni. Hui’hi uzbw xewukmotj dwo xevnerki yo jca hfape al vpu zyuma ux ska munogy.
Ocurfqwiwb igma mnok guv ot qegmowb oybane lufqola.
Ray casting, ray tracing, path tracing and raymarching are all ray-model rendering algorithms that you create in kernel functions, rather than using the rasterizing pipeline with vertex and fragment functions.
Signed distance functions (SDF) describe the distance between points and object surfaces. The function returns a negative value when the point is inside the object.
You can’t generate random numbers directly on the GPU. You can use fractions of prime numbers to produce a pseudo random number.
Fractional Brownian motion (fBm) filters octaves of noise with frequency and amplitude settings to produce a finer noise granularity (with more detail in the noise).
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.