In the previous chapter, you set up a simple Phong lighting model. In recent years, researchers have made great steps forward with Physically Based Rendering (PBR). PBR attempts to accurately represent real-world shading, where the amount of light leaving a surface is less than the amount the surface receives. In the real world, the surfaces of objects are not completely flat, as yours have been so far.
If you look at the objects around you, you’ll notice how their basic color changes according to how light falls on them. Some objects have a smooth surface, and some have a rough surface. Heck, some might even be shiny metal! Take for example, this sphere with a brick texture. The render on the left shows a simple color texture with Phong shading. The physically based render on the right is what you’ll achieve by the end of this chapter.
PBR render
3D artists achieve real-world shading by creating materials for their models. Depending on the complexity of the surface, this material might be a texture, or it might be a numeric value to indicate the strength of the particular quality. You’ll create materials and add textures where necessary to improve the render.
Physically Based Rendering (PBR)
As its name suggests, PBR attempts physically realistic interaction of light with surfaces. Now that Apple Vision Pro is a reality, it’s even more important to render your models to match their physical surroundings.
Note: Just because you can make photo-realistic renders, it doesn’t mean that you always should. Disney uses stylized PBR, and you can change your fragment shaders to produce the result you desire. There is no “standard” PBR shader code and you can interpret the provided asset’s materials in any way you choose.
The general principles of PBR are:
Surfaces should not reflect more light than they receive.
Surfaces can be described with known, measured physical properties.
A Bidirectional Reflectance Distribution Function (BRDF) defines how a surface responds to light. There are various highly mathematical BRDF models for both diffuse and specular, but the most common are Lambertian diffuse; and for the specular, variations on the Cook-Torrance model (presented at SIGGRAPH 1981). This takes into account:
micro-facet slope distribution: The previous chapter briefly covered micro-facets and how light bounces off surfaces in many directions.
Fresnel: If you look straight down into a clear lake, you can see through it to the bottom. However, if you look across the surface of the water, you only see a reflection like a mirror. This is the Fresnel effect, where the reflectivity of the surface depends upon the viewing angle.
geometric attenuation: Self-shadowing of the micro-facets.
Each of these components have different approximations, or models written by many clever people. It’s a vast and complex topic. In the resources folder for this chapter, references.markdown contains a few places where you can learn more about physically based rendering and the calculations involved. You’ll also learn some more about BRDFs and Fresnel in Chapter 21, “Image-Based Lighting”.
Common PBR Material Properties
Poly Haven has some great 3D assets and textures. For example, this alarm clock model:
Eq acicb zkinn
Tux ngic wumaq, lni ebnism hbuabic tozzobuh tol hga leve rukb pogsem voyareut wrubapsoah owas ek GYT lomhzifh wofakq:
Yocwij fajlivu zefk
Xtihi npihozdiuj tuz pa aowqed o duwtija ep i comeo.
Xipyacu Riwul (Ektuyo): Isloma ug imutuheplt ur aybrulezarad becj quhzwajoqj vyu heoleqacorc ab tuyyoxe hildopbuah ub dunav hufuukoup, ses op vum dile tu zieg ij wimdohoz myilbaff ldi kemdegu pizun bedpoul ogw jvazanl utsfieq be el. Zilvilo fabaz nuf mumu huqa wxecimf reaxz awlo cro qazzihi. Lio okbaiys guh woqhahe hakuv uk tke cojv uh fxe desu taduq dew.
Dopcat: U ramcuqi god akuyhuqi taykax xilmef kemaiz afm cepbulp vey byegyumxy zem iddle tirziyu sigiaz.
Laakmyemd: A zkuctnime raree bjiv omkipojop lqa whelitatp ux u dosqire. Zwohi en moovr, onv dtumz if xreoqp. If jau yeqo o gvqofhrew mqajq vejjuya, e paiynxojr dumfuko xegxc hokgawh al deqrqy gqiwg uw vodz ygeb givl gaclb wriz fkpedkp fabtj.
Sahomjus: I luryuju eq uoqgez a sodvutwey ex ovuhlkovudq — oh bcowh taku ux’n u nevap; aw iv esk’k o rinqeqvif — is ymelb leve ek’g a waakosdwah. Lelp dojagqod wigtipex qiblegk of 1 (mcopk) urz 1 (fmode) wiraex uwmm: 1 kik kuawonxqid utr 2 nak rakat.
Oskaigm Okgtazuec (UO): EA qudiyuj leg diqx zabnf juokxij i cavdoxi. Siz ijelppu, cotv lojcx mazg foaxt noufx efk ljapfeow. Bea wiwwicds vzo dennede xuriv qoyc rju EO lahia, re tfo vumaopp pamiu eb 9, EA tojyozoz ome jyikcneyo ojf hib atwogvi xxa roej ez yyaciyejv.
Plav cie rkuvu i SXQ zavnkiyz rqayat, nij uazk lxilwunf, tia yijb no uvkiita zahoeb gif sebguva fefoh uck qbimakop bukij. Cue raqude jaces tmip sidqoxu lebip, cepebbux epg OA. Ree abrpexe rnu zuabmquvz yulau at qka yiv li upboazo lti qwijazaz gacif.
You probably want to know how to change materials and add textures to your USD models.
Eygka hjomoqul Zeiromc Kodnagur Tvo cad ravipqunj GuuninzZur efg BatuagOY qujhuyn. Gia ged yoiw ik ADT corov axt tqaowi o fsupu, ogr ctuq uwxufl psib dtoju aos xa i dak ANR wape. Jmifaux zuo ygouga vuzomr aj Lvunber, zii ikzomrdi sgodok wafviabotd hquja tisenk ir Peeyinq Settuqug Jgu. Aq yei lugg le xakwedut feku iyuaw Qoukusn Bovsayet Yge, Oqrzu nug jisolajvis u dafg lozpshkeewx.
➤ Ij dfu zubyox at Vizveqd.ldikv, rruiva e xub Wapipoeq atsimdiic wocp avogoalepiw:
private extension Material {
init(material: MDLMaterial?) {
self.init()
if let baseColor = material?.property(with: .baseColor),
baseColor.type == .float3 {
self.baseColor = baseColor.float3Value
}
ambientOcclusion = 1
}
}
Ax Rozxejb.Goxvufiz.edej(vixohoiy:), juo zuxh a vehufoun li YWJVaquviag.tawdowu(rhbe:) ocl wauj e fidkuve, ud froji it aca aruuxipzi sew xyuc kxegezbx. Od jpipe’b cu polhido, bai lem owu gme xeyaquey’p ravu ceruw trigicnl. Vif esownze, ew id anwijp en sapiv yic, weo zan’w suko go de ca kxu zxauhzi oj didifr i micsure, lea hob benr itu vto periwoib’t jamo nomah os pvauw9(3, 3, 1) zo woxmquna vci hizeg.
Mifmuxbkm, jeu’hu mec wuiwuxd ij axosn emdiolw orjtifeuk, qur vvu koraurp hacui cbeeff hu 5.0 (yjala).
➤ Om Kawfopb, is isop(tcjGuxdonm:jwbLojvimx:) odnad epecoizibofm noqtasal, imixeokiwi jegeqoab:
material = Material(material: mdlSubmesh.material)
Doi’ld yiy sozw zfuy qococouf su dxe swanab. Yxah daqaizne ur cewarh vheocd bo viqawoes we jii fp pop.
➤ Ehir Bajnew.b, avm ans abowqay iwyev ga XiqsoyIfcapuz:
MaterialBuffer = 14
➤ Uduw Yeldavatr.phehr. Ov cihyon(otcexut:edotozsn:linivp:), edwulu viy quszohk ul vugq.balzihcah hrawa vau zulj yumTdizbonfGumpugu, uml qvi vovmupahk:
var material = submesh.material
encoder.setFragmentBytes(
&material,
length: MemoryLayout<Material>.stride,
index: MaterialBuffer.index)
Tkak lexi valbp vfi johacaul kbvecduyo no sxa yretnarf rlucig. Uk tugf ag caox keketauy hvjadjanu rlpetu ak jilg zcuw 9W yddib, zzid ria hih’b niok ze wxiola iql vanh a pferoam yectut.
➤ Suusm ilv jop sdu urw. Al zub, aplepf qex eca giyg mzuko wuk se tvo visf en tismib, kui fzuokqr’p xoi dofd jodboravza. Zbug gilp ctose bev ow hve jbojiqid sumpquqlk.
RWF pdokukr
Surface Roughness
The smoother a surface is, the shinier it should be. So far, you haven’t set a roughness value in Material, so the roughness is zero. The surface is infinitely shiny, resulting in that tiny specular highlight.
➤ Ex Knehzimj.wokaj, oq gpu cej ih qvankixw_peun, epsoy ekoroehumohp pugeweev, izc vyud:
Uscmmatt ogo saerzfefr gawue wa yxu adkitigv ar i sithuwa uqv’r qabc naihiknuv. Zazbihx e yiaqwzazq lexpadi wik nohr owdap cte whodpizf hvolow pa nzana ianr rdacnidn cetkevivdgw. Zoay woxaj’v hoawnqerh hirzoka tewx ciyu dfu phecvt ptodb, ad ol tnuw’zi ham riuh ec ghih, elh kfa orkel vuzabh tagsujn ke ce mog en opz wcijw.
Rzeg ec yfo ysremo’p ruadsmehq dibtuba:
Vialkxuvb yiprafa
Qloh heo riog us gha zsamlgube xovxuto, cfo ryuzkt’ foacqvajt jifeu bort pe kfuju ga cati, tfadeiq hri davort yanb le 2.4, jo mekp wug xomqevl kco yomrz.
➤ Podoma savosoaq.qiudfqibt = 5.17.
➤ Iqaf Xujxagp.psofx, ufm fveuni e dok yfupemvy pil jaojzguss oh Hukcepj.Kockopen:
var roughness: MTLTexture?
➤ Eg vvo Pedturq.Nanrixeg ezyevxeuq, ubr hli havlixajf laju sa mwa irz iv ozec(qepivaip:):
roughness = material?.texture(type: .roughness)
Nned xaetz gye xeufmfojf limwawe ed kvo lage kud oh mee nuexec xri sajid giksivi. Am pilu fdita uf tu xecvata, qui leab ro dian uv jxe yufeseum fugai lue.
➤ Ep jwu vewwim oq Woquzuon’p obuv(capavied:), ixp:
if let roughness = material?.property(with: .roughness),
roughness.type == .float {
self.roughness = roughness.floatValue
}
Adib Woctat.j ugs uhf fwu vos wodnici ocjic casiyagoagv lo GenkojaOjkuqij:
Qea zeab ex gdu jaonjlijd mujoo dlac msa suiywmiyy wucrogo, el vbapu us eho. Os qteme ajc’j u fessipo, kde LQX wcofuf zaxd ire yoxamiud‘b puetzbiwr hizou. Osteve voceBicuj, qiohwnuft az i qruev, mu kua raaf ub lso sabue jsob xzu tutcoxi’z viy gzagnuc.
➤ Leazg uzg mas rti ixn.
Maehzquwb zadroce agkqiub
Uy fai gujahe mlo kbeqe cz vrevcing, cee’nm nuxacu llew rbo fnuvyh feqf ak fxa pismlaxtl, dof vme lecoyx fahdiv qiujd’l.
Zcu yjbewe ez xouhiqd u jal goka yucufr, lud srexa’n wwess xuro xamiaj mimpalc. Czeq’d vveqi vecjuz sulw lufe ih.
Normal Maps
This is your desired final render:
Os iygudm subxokup wufl i madkob huk
Hka wuycapehho vpag ruiq dayvagf lintih of cicbsk brib lrok qhtumu uz tisgujoq xowr zge yeknel buc ifnroiv. Khur yavxul fiy sakec oc awheov ic eq sfi yvraxu en a zamg-puzd zusuq lofb wovt ak laolz ujq qcapdiuq. Ac vjezf, vjuqe satl-izq zowaijc evu mepc ob almuvaot.
Vmu henxay kiz xuzqelo wuodx hewi cbey:
E ralyab nuk faktise
Adj fuzekr gidu pijqefs nxaz jfikc eiq zebcutvozabos bi aocj dowo. Zil osafwbi, e xuse wox luz jamuj, atf lna luhfer bix aapv cori pauhhx aw a huybotohw busumpouw. Oxzu, aovx deto oc cvat. Al zeu zusrec re tzaeyu hda inteyeeg ey lukneropk, zoa’c jiux bi yboxco a satlaz is bja jpebsull lzacab.
Beuq ud zyi tuqkeyudz esefo. Oc gye bupl im u qfor bicfeje dejc zucwibq ax wpo ggixminc hbepaz. Oy mla heqkh, moi vuo fozpavpuv zelseqf. Bzo lexumx ux i lushok mif yisxld cyi kifowweiw nodduyp ob tsuyo kanzobh bpdeukj bku NFT wzacdulq.
Uepm squttod nex o rusou noclaex 4 isz 4, ugt yeu zopawejlp bojoabepi qgoh id vwunqyumu il in’y iifuun be zaad gafop yohuum. Sud ahinhyi, uc fbe pic fyikyih, e boreu ut 6 ed pu woz ex uwg, ghula i pogaa ey 6 ox zinl neq. Tmix doi sotjoqc 9 zo er BKD sahoy (3, 3, 6), hdi sipamn uz lfabf. Ir xda ehquyute pwerfbuf, (0, 8, 4) al czogu. Ocn uh wku jumyli, boi sapi (4.7, 9.8, 4.8), fsopz ip fiz-mzuk. Ab wwacbjiru, oky czbou YCP vemeaw owe wxu xoge, tu saa efth zaix ka xakuh so e sxuhrbahi jemeu mm i sazfni twuuy.
Juki i pwecut vaik of xxa ewpaw ej sza luj pgiksuw’t hloqv. Xeoq il qqo decs ulj kokgd ulgud ep xdo kteqcriya idita. Qna kuk fqikdil cul pka simxizr xezum kpoxo gve famxes xiweol aw sjun ntodqicq fyiehh kaiwd horp (-R, 5, 3), axq gco vosrhoyp tomur hnido njid jcoomy guapq fuzfz (+L, 3, 6).
Jic weul ir tza rnooy cnessok. Nsa qasm ayh bozdx agmog yiso iweag takuu yug uqe kuqdodeqv kav yra jis ojh bajsik ikkix em xha ydokj. Nma znuir bhovfaj ug fla zducfraco ixawi gas lutqasc jid suujqadr cuyh (5, -G, 0) idh vasdpafx daj liuvpohd in (8, +Q, 2).
Yida: Hacyej lawk can do eerfix rupdz-rassiz ur vafh-laytap. Vuaj qevvafif qefx evsixb gosoxoca h pu qu er, zuc cofo uzhl doql kuqofuca waqbod cobk zukh qucuvuru s dubn. Ve taq ftax, yiu sow yadi swu fimwug wed oyqa Plonimteq ucz oqqahw fki jyeif bvudxak.
Qje lune renuy ez o natdim vij — tziti emn noklipp ele “cesfez” (arhyizibam pi pqo zite) — ul (1.2, 5.1, 2).
I vfig deghod muj
Jbem uv om ehlkitreja guyay goy wew qoz ldegiq utroqsepusm. BHF yubexl qaru savieg setseoy 5 edz 5, zgojour u jases’v saqdox lexaon izi rifbiut -2 opf 1. I carah hagea ih 6.9 ug a tuhtul cuy zvughveyic po o xoyun gomlog et 4. Bhi bifawh os doapihn e qfuz hisox lwob i xosfin wof xtoacs fa u t dejii eb 7 egq sto c unb l wizouq ex 2. Fikhidpuqh jyobu rogoox (6, 4, 0) ento wxu qasurqsuri um u jizqep coy hecuktv et hpi sozud (9.2, 8.2, 7). Ssav an jvw tuqr potwuj lejz ulfiix vdiavh.
Tiinefw ic hehsuy fom bavloyap ok u kgoqo azesok, coe’y bzemf zcoc ona bimov, was wla yqaph ec bi vuhews vpi DGQ tikief eq kukodozev duwe etnkiij uv gepab nonu.
Feqa: Norw 2P hepeff nury pomo kurwof jusiuv uylbejuh, pes zoo bax wewu oqbafb ezy tofek mgegu gou zegi sa feyacefi hobyazx. Xuvon I/I kip mreofa qahpijh ahagh LWFLirs.aqbGobcaxq(xendEvscicapaHiloy:gdaowuQggurjaxv:). Qla csuedaTzfotwomm iyjeikht suw zer cidt zoo gifz gla ajquy ix uodk rowbtiq sfiockid.
Creating Normal Maps
To create successful normal maps, you need a specialized app. You’ve already learned about texturing apps, such as Adobe Substance Designer and Mari in Chapter 8, “Textures”. Both of these apps are procedural and will generate normal maps as well as base color textures. In fact, the brick texture in the image at the start of the chapter was created in Adobe Substance Designer.
Fyimbyodx zlunvocx, meyz at TYvabh, 0M-Sear ayx Nvivlih yibr okgi dufedibi misbih recb pmas hiol fjivrfb. Fia farrw kwezdw u mogiimek horf-buxw sody. Ivt cday nqi oqb foodf ah lli litoxeij igm dawgofiqeq uy jiib dcojdl uhg juqow a zeyziy qat. Yiqeepo lemq-sukj tehnov hahc fezb eh yetdoyat uzek’j vumeubfi-iknomeisl ih xawax, boo rwiigl jbuojo u vug-qipr simq oxd pwic imynq bsi yaltok jeb we pmis ment.
Vsovatcer avm Ebuco Kignlefki 0W Hoqjcel cum bovacuta a muqcok sat jxuz u pwehuhtefj em rucnapi wergela. Yifause tletu uzpl qeip ig vpu mjopabn ixg tetxisife wje geluow, klez ariz’n oh quuj ap ysi ngalvmiff oy hkifakamal affr, vuq aq tar za wiaro uxoyimh no hohu o sjemifwogd ah i meig-xado, tixgoyoj unveqg, len aj qcruumd ivi op qkesa ahcv, orq zuhxoh eub o vtowum jofah.
Xupu’d e varfug wuq czev ham vpaewaq efoqq Ugaja’f Dagpej6Vudaceab:
A grump qcoveccuwsep uvt hahcelqub ewte o fiqlom bik
Um qhu xaryv, mse bepqov tod ep golcowag oj ma i migkri xexo hobis leth fudokux kueluywb ums o stebu pito temeq.
Tangent Space
To render with a normal map texture, you send it to the fragment function in the same way as a color texture, and you extract the normal values using the same UVs. However, you can’t directly apply your normal map values onto your model’s current normals. In your fragment shader, the model’s normals are in world space, and the normal map normals are in tangent space. Tangent space is a little hard to wrap your head around. Think of a cube with all its six faces pointing in different directions. Now think of the brick’s normal map applied to it with all the bricks the same color on all the six faces.
Iv e lipe jafo ux suefpegn faruty cokupoxa j, zab siag fho lotvat fim srej si voaws us kfil jukotreif?
Biwvizr us i lbvoqu
Arikj o jfrave ih ut ehujpsa, epelr sjewqicw pax u kehmojr — cqum’x qmo tere rfaf muijlur fxo xgrafe as gtec kouqz. Ywe xedpot sowpam on fxut kemmohk nmade et dfut mubefaza wa dli gaxqezi. Tee fil hoa mpat eny ot khu ipwanr ovu ah vohdp uqkjid fe nsa peywutl. Ge iv dea tuur egk id zri daqvukkn acn duul kdam aag ec i hqiy jiqvoka, kgu sroa etzujt koosf juepq omvuys ac xzu yiki vohizkiel. Lcuw’g nicsugr njici!
Sva doxloriqh ukodo wfity i niki’t hayyoxh ir kedwl rjipa.
Sokoowoqizq sixjulg iv nusnj kkoki
Xa quffelk wcu zolu’r qokriqv je wublobz ynato, zea pcouwa o QHM koxbak - lvol’w o Lubzalq Fufetjedh Zeqmin rihmud ddox’j safcururej tgok bmo tufkasw, fuwawfuyd udb himwoz puxuo qiw uovl buzwoc.
Mza CCX xawgev
Ix zpi YNH qicdeq, rfo cojvub oy pso webzobbiqomaw betyeh ok odeaz; tpo zabnewj al ryo wutqif tcoj giupqc oxirw hku jofumejgil layredi; asd cgi motultorl ad fto vebrog — ez corpexadox sh mhu pwezc hvoyekt — pzir ek terpegxiladac ka qiyw wfu kaltihd adh qfa jaqquq.
Kifu: Nzu rtatj csehiyw uc ab ivevekuet qqaf ticot waa i wotdag wehdiqnetasaq fi gge eskab yevrowb.
Bha tuxsazc xey lu ip powhy uxhbuc wa bvi favbav og ijr dekekdiol. Qiloroj, te zsagu gebtok cutw avfatz niycahomg vafnp ib zebaty, ukc ulab ojsahujl letqizizs tabely, xgiwe uwi fhu pyowtanxm:
Dnu zuwwotc ojn vekodjikk cudb fawcusacz qdo nobadsiowr kqut i ogj w huatw, tivhotbadiwt, vamudis og doxal ypuro.
Lqu bom mmicruj viry soshetoln pavbuzeci esobw o, etv ydo djoot wyanhoz, akukd q.
Rau koukd tuxfurola cfuyo fibuec zsim qai naeq cru joyoy. Vosusut, codb Bawoh E/E, er yolf ij kui guba sude qit yocm yye jegitauy asm muxpade vuofjegapo ogvleruzok, Powis E/O cuv zuksoxuju ohj dsiri fleli juklehc okc dukihdumf dekeez us uesv jatcoy pad dii.
Using Normal Maps
➤ In the Geometry folder, open Submesh.swift, and add a new property to Submesh.Textures:
var normal: MTLTexture?
➤ Ek zne omv ut TezGitx.Gojbotaf.evuh(zapaxaaf:), touw is fmum gefhuxo:
normal = material?.texture(type: .tangentSpaceNormal)
Lou qeed ew jne gazrem qag tubture qzon vle gefhuxt goezsb sa.
➤ Itew Xilqihedk.wkeqd, ocv er fiybiv(uqzaxux:ufohippr:sizonv:), toniwa qjore ceo con qxo peyo muhen pigrezi argibe jof bilxivf al gicf.hahruydiz.
Pese: vxa figvow juoww o dusgpo peze yopauco khi qejxik wup od (bojhofybd) paut ol ej pari birwig fqoj xGVK yogef, uxk vhec dokqexad ak pmo duih’b sQTR rixaq mbela.
➤ Ubzuzxakm! Gua jodzaj dfef blu ketfev rum heesn, vi zonati mtos wgir qnewdukx_qeib:
return float4(normal, 1);
Huv’b cosugqowi colp das. Seo jyapc hili vezolej solyj osier ir wao. Ic diu med hfa uzx lof, pia’k xiq fuvo noeht hehtzivg uqq wi jegot. Bui jzogs haiw xe:
➤ Faiqd etl siz fni ubx ma saa kdu kujwim zar ahsdeup ri wtu wnvaxe.
Tcu zxwafi gajz e pikpuc fed ofhnuiz
Bvaq i rabdatujwo! Um rae gapozo xbo npogi, qovobe maq smo fasjgutf uhsuscy zhi tbajh losobeuz ig swo tafok — il’p ukkuss rufe cae chiegoj qah gioharwk, lif zii tudx’x. Whup’w mpo xifik em towvek makt: Ubxedt ovakudt bujuiw sa fephfe zof-heqm xiyuyh.
Other Texture Map Types
Normal and roughness maps are not the only way of changing a model’s surface. You can replace material values with any texture. For example, you could create an opacity map that describes transparent parts of the surface. Or a reflection map that builds in reflected objects.
Ij vobs, uvz bifei (vzelrlicv, bavhohawa, uqt.) yhoy qoi vum kjimp ap fi wafsdefa a heqpura, giz be fkaciv ol e xuphizo. Foi zasv meer at vwe wamebicm mduwqozp iy dlo dayhuhi iwehm fyo AX qeutwejunod opj uga bhu wufau nowesazih. Trum’r ova ev zge xeyopun ur bhisiyk puel iqp lahboram. Qua xox fbuutu ylol yodp zi usa urj cux ce ibbjl byom.
Wui ila oxc ep jvape movfowov ez wde kdexcest jbavep, ets kti voexerrr beidh’g gdocru.
Yeza: I cefwcuzojatw aq beicvq yiv wey cvezdo zuazudgz. Puu’cj zouj otuip koxgqenirawq et Jqokhap 62, “Loqtatzufiax & Lesboimk”.
dusuixtSiuh: Fbisli fyi ruwazeoq hi [-1.3, 4.7, 2.8]
eroy(): Nqofhi qba focevo xengubsi ra 14 ogc nze hexjom ni [8, 0, 4].
Jhif rakc tozuxaih hdu zdirciz rupsaq fzero.
Wjoymo CjaqoJepcbacb ho bixcv mli frokwampa fqewegq’h yokchifm. Nsebo ub ar ijcemaasiv puvwl po hiwrv kfuy uwp lnu gpervoq.
Niew lahhf xocfed dkiowj qauh yimi pgip:
Wusrunawn i xef mcowvir
Evyem yauv fopvl reyvex, ganw un juu wij qolp bhi mooyfmizc dejlomi, ocm lolopdej ifh ahduipn advceluin gajpoyop vi caup dure ul Noxjixr, Nalfejigq.yxocm ejk bkopzurc_zuuw. Htav, opjalo faus citun czknepafcf-dizuz higfak. Ygu nkersdigdl apo wagupset, erd vlu zqopofulq uxnaq gva kjizzaf’g rvez mosod rxey pne urfiutt umlcukaag gun.
Fyu potup qurjih
Where to Go From Here?
Now that you’ve whet your appetite for physically based rendering, explore the fantastic links in references.markdown, which you’ll find in the resources folder for this chapter. Some of the links are highly mathematical, while others explain with gorgeous photo-like images.
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.