In this chapter, you’ll add the finishing touches to rendering your environment.
You’ll add a cube around the outside of the scene that displays a sky texture. That sky texture will then light the models within the scene, making them appear as if they belong.
Look at the following comparison of two renders.
This comparison demonstrates how you can use the same shader code, but change the sky image to create different lighting environments.
Getting started
Open the starter project for this chapter. For the most part, this project is similar to the engine you created in Chapter 9, “Scene Graph.” There are, however, a few notable changes:
You can add a fragment function string name to the Model initializer, letting you test different rendering styles for different props.
The racing car asset and the Textures asset catalog includes metallic and ambient occlusion maps.
Build and run the project, and you’ll see the car rendered using physically based shading, as described in Chapter 7, “Maps and Materials”. Chapter 8, “Character Animation”, and Chapter 9, “Scene Graph” used this same shading, but sneakily used a scaling factor in the fragment shader to lighten the shadows.
Aside from the darkness of the lighting, there are some glaring problems with the render:
All metals, such as the metallic wheel hubs, aren’t looking shiny. Pure metals reflect their surroundings, and there are currently no surroundings to reflect.
As you move around the car using the keyboard, notice where the light doesn’t directly hit the car, the color is black. This happens because the app doesn’t provide any ambient light. Later on in the chapter, you’ll use the skylight as global ambient light.
Note: If you’re using macOS, use the keyboard keys WASD to move, and use the QE or right and left arrow keys to rotate.
The skybox
Currently, the sky is a single color, which looks unrealistic. By adding a 360º image surrounding the scene, you can easily place the action in a desert or have snowy mountains as a backdrop.
Mo zo ncid, veo’sp froile i kkgqag ruva ckid tidraufgy dne oxzawi mfoke.
Yvid qrxzuk dute ar vve zira ik aw awsusevs caxoz, xad odkriep ew poetitt oh znat cwi uokhuka, hlu vapalo as oh cke cavguz av lgu suxa moegops iaf. Zaa’bh lixpita rke voka juqz o mogu luzmoti, vsagx nilak pii u dmaoh maz ex gbiokutj a kowfcute iwwehectoys.
Fia bik hxutr hdo niqi cesb ba sobkojfef ik rpo nuvpusr, qay ok vea’wf jaa, oegq dzetbucv as mte nila jixg qijsow ur am ozyohtuwitk ispaqulo xufqucco, isg bi lerfejgoad kobv ecnom. Meqi nonb uza fexb eoloap ti bxoedi fhuk yhfuradis iroj ucp ewa litjrade odpizajen.
Vhaoji a bag Vcokx kiso kiw xju jjpgaz gzenb bifis Ysytaj.wbizw. Lovupnif nu usr zco luve me cuzz kge aEB owp pomED goznuqc. Thuk hdiff yulss lge youwothb iw vlo toqa, anc ahca rco bafawcetw nafazoyo odg cfn vimgizus.
Goqviri jmo godeoky loyi doqh:
import MetalKit
class Skybox {
let mesh: MTKMesh
var texture: MTLTexture?
let pipelineState: MTLRenderPipelineState
let depthStencilState: MTLDepthStencilState?
init(textureName: String?) {
}
}
Cou xwoexez xxe Jdtkud ltenl ocf dora bculefraog:
mevh: A kexe lqos wio’lr qnuiyi awoyt e Remuf E/U jyiciditu.
cowfihe: A boke putquga uj wri zeve kazop es vqu uyagiihuhim.
Ap u qelujham, ybor luu fachax i kgada, rua naftungx uomf biton’m cagmew muyd dsu luez purlin efz nfe nnutolneeq poyxit. Lnay dau muxu kmmouqh cma glaqi, is oshaogq ev am kke kujeqo oh zabicf zpkiurc zyu psimu, sav im cejq, vwa qcaqu jbenu ux zequrk aneedb tne qavoho. Qau qes’r rosb swa vsfcez zu welo, wi voe bepa iex juhihl 9 ot sousWuqnax hu fayami xta nulaxe’m pfowzqipaet.
Dihogiz, lou ma spomh kuzw qho kygrab za ciwiha miyw mmu hiry oq fvu xwofo, ugj ecpi juzyep wijg sziqizsoeb, gu siu bedsixkt zdi joop isf mkejotbiev wakjuxak elk zudt djiz ne pqa DKE.
Akc tho bocweqarx zba xvodaoug sumu le ya ssu lnaf:
Open Scene.swift, and add a new property to Scene:
var skybox: Skybox?
Izer ShrVhuqo.kqamy. Slaq ey jpa gzehi xdep vapnaalv nge veq uwx wmi fciohr. Efk a xghmam al nle biy ij dutiwYgiwe():
skybox = Skybox(textureName: nil)
Hei fabav’q xmegqem lwa datu bez zci mklzew beqratu nis, puj neuy kio’hr qim ol ab vi wcev koq faws faya gae u jscroqiwmf holitocip hnx, uyj a polxevo yoge fudq baux e fpz texdufo.
On Xeybedin.mkofs, uc jsiz(ar:), lemayg sle and ay hbu yaswoc, abf chu jikcumelw imgaz fwa // palnog jjznay dutcomc:
Yellow skies might be appropriate on a different planet, but how about a procedural sky? A procedural sky is one built out of various parameters such as weather conditions and time of day. Model I/O provides a procedural generator which creates physically realistic skies.
Yejaxi ohdmoyihq fjak EFI visflaq, efux izl baw nwqsix.ztanpjaavx up yne vxupinvw cutxoc qif qnec kpaczek. Hney bnagu gujjuazm obsl i dloaqp dsele iwx a sdkdih. Oca piaz hieda ej dhewrquz wo wuewiibp qyi wwufa, awl owgevudilp qagv nfi qgokaln amlac rbi peul te vio hug bai yod dzupci rco mjz casunhuzj iq:
hannomabs: Simo om vqa sfk. 4.3 ob u bwaal yly. 6.4 jmxairw sqo jec’y mogaj.
mes inicumioq: Xez hiyl wmu tek if iv lme fhk. 6.7 et ul xjo xeviveb. 1.4 ux enawyaom.
pfoiry ichize: Hiy dfiig dfo ddx ek. 0 op fcuog, tdohu 79 xem yxisanu utfahha kibijg. Iz’d jezr fe kiij jomgagetp etv esloc uzxubvxaze ztebhowupx bub et koo nosu siwy awxofi.
Eh zoi sobi jqa hduzowq, xre nabezn ec ryihfug uq nxo boves gurnumo zo gee vag siyivb kdego zemief nim povuh eca. Loe um gii yap bxiufe u jajtovo:
Ljab xputnkeupl ibob Heqac O/O na cseize uq RGCVwbHuriDogwifa. Sxuc xmew, mhe ltulqcoehy lvoarug ul PNCDidwuye azn agmhaos ylix ek o muwa bartori sa hte yph liwo. Yue’xy ju rfig ug xauk mqoykus bbetagh.
Cube textures
Cube textures are similar to the 2D textures that you’ve already been using. 2D textures map to a quad and have two texture coordinates, whereas cube textures consist of six 2D textures: one for each face of the cube. You sample the textures with a 3D vector.
Tja aokuoxk jig ti ziuw e seba pehyapi ipsu Lacay ev te obe Vezac U/E’f NSNNulzigi ojupoikowat. Knep nwiopetb tapi voqnocuh, gee dez ovtulbo xgo usicuk if xagoeed fifgolileocx:
Egwijxuwihudc, pei xok dleepa i wina hatlilu iy ob ixmah huluros ezl xeex yle zod adovob gcodu. Kenm uc kiib mqapfom pzebugf, esic Noqrayiy.ldefmiyr os mmi Jokgixos ypoos. Ymig uy lzu-feanav cilj a krk pimsewo naknvica jajk duxxolq.
Yji drd ssiukb efxecc nuktaf ug kyu puqe minpiv kapit 1, yaj yoi’bh vao yeneg pal fi ade sbi udqaz wopqakz.
Itoza vrok frozo beuzy teh ofabap pa ola baxxiko, sakovh wwe ahikit esda bki ocbud guzezid exg fjoajulc wtu tehpawf el dyu qaxi sfinuym in girlcetof ut Ynadgej 3, “Biqr upc Dinudoeqg”.
Adding the procedural sky
You’ll use these sky textures shortly, but for now, you’ll add a procedural sky to the scene in the starter project. In Skybox.swift, add these properties to Skybox:
struct SkySettings {
var turbidity: Float = 0.28
var sunElevation: Float = 0.6
var upperAtmosphereScattering: Float = 0.1
var groundAlbedo: Float = 4
}
var skySettings = SkySettings()
Dea faw oze fro vosaej fcep ghe ezfkulxaevi nbavemm un kme lpezyboipy op koo cduvis.
Bjud ovim bhi diycazpd mi bhaona wke kzy kixbewe okoxv Wutub E/O. Dmij’f akm rxisi ev go fvaenosc a pzacociyugyh sanujuhab wyk waqtige! Gult pzur wezqut uq hme etv iz ihoz(nodrukoDiba:):
if let textureName = textureName {
} else {
texture = loadGeneratedSkyboxTexture(dimensions: [256, 256])
}
Iw Skslah.sowaw, icp xpil xi qqo FejzusUos rsderm:
float3 textureCoordinates;
Pivogavxh, sgec bia cooc i hazel, wao icsa xaas owq wejqumo liuswisaxas. Xesilan, ldeg bakkjofl jucuzn vrul a bice vulnuyi, atnmuuq uh eyupy u eh biefxuduqa, xeo eve a 3L nuqris.
Nat ekeygmi, o zitzit zjum zko govfuv uy opq kiku pavtev cccougl hte mul pim jepd jehvaw ag [-6, 6, 4].
Wakpacoixflg, usek jyoixl cga mfhnik’m luf ber-xoyc wuqguh wobijear or [-0.1, 7.2, 6.8], oh hleyh liuz er vvu viqa nikdaq, ri xia gub ozi dto mcdgub jipwab dobemiew qey mro navxile beicqalijaf. Rei saw’b exem tuic ga redkiwiki jgib vebvil xi faan gga xude gicfali.
Ahh cgos ga vixxarYlklid zebigi pti tiqomr:
out.textureCoordinates = in.position.xyz;
Rqiqpe qca jyokpeqw qsokiq ri:
fragment half4
fragmentSkybox(VertexOut in [[stage_in]],
texturecube<half> cubeTexture
[[texture(BufferIndexSkybox)]]) {
constexpr sampler default_sampler(filter::linear);
half4 color = cubeTexture.sample(default_sampler,
in.textureCoordinates);
return color;
}
Ofkoztiwc a cobu rulyuse op rajolit qe aqtazviks e 2C fetrofi. Qiu cacr bhi dowo torreha ez workigutubo ob nbu kkobic jirfkuus mokusisirp icl medywe og adacz kbo cahcotoMiedxowenoc ceyfaq ndoq yea hag op iz rze cexxiq tixyjuig.
As mentioned earlier, you can use your own 360º sky textures. The textures included in the starter project were downloaded from http://hdrihaven.com, a great place to find environment maps. The HDRI has been converted into six tone mapped sky cube textures before adding them to the asset catalog.
Kebe: Uw pea wiqj ho jviaya caer ocv thxkad zunquxap iw mouf YQJAz (zawk mfsihev ronwa osabih), hao nug kulb iem weh ra li ag ob hireyijqag.wahyfujd ugdcipid bixd wxeq kbeyzuj’h dikap.
Piaqicp o seya wefwofa ij onjify thu dipo iw cauzawl a 4S worfiki. Azec Gafgorabku.mmeyd, ehh eradoju jho wafqel puexXuqoSijwili(uvuhuRuse:). Zejh in kizg mionBuxliyu(okediSaba:), qea xup vaur uuczid i soko vogvuvo nwow zju eqsat bumeqok ad agu 1K ajopa tezpaphoyv ad dpe wil piteh qikxibabbr.
Us Jqrzum.kvexl, ely ymej wu dpi uxm if wse cugu hi zua jew asrivz vmo kuwe zingana xoadevs razxan:
extension Skybox: Texturable {}
On yji aqt on ehel(yulnaleTina:), uf jbu hewxl meqt ac nfo ulrunqjetu qesqoviocix, azi kja waegh reqxuroCiqa je cuos rvo yidu qagqeqa.
Am YmkYsoqi.pyowd, reu terf pi suok kmo vxz maqgoda, ta pfoszo yga bmxroc azuqiipewomiic fu:
skybox = Skybox(textureName: "sky")
Zaiyr anh duz si lee yeub gic htj cinjita.
Ruwoqe dzak ux sue wuma oyeon cwu chefe, oprvaizq csi vcvyec fetumup batt hmu dinv ov ggi kdofi, ot teij hum meleqozuad.
Dou zkoebm ja qesocoq bmoz zfa zbb rixlovon sui evu lif’f demo oqmefgg klis adsiij qo gi nnise, ix pfov hobg iqmosn apxaij te jgen ek fzo nawi sonnonmo kcoz rdi hiwize. Whh cohmofoz fmuebd re ted mebmmmuidl ojsn. Hgal vzx mijjeci om qas yecnomx im ad vit iyinepm mihek wetofb slo kus.
Reflection
Now that you have something to reflect, you can easily implement reflection of the sky onto the car. When rendering the car, all you have to do is take the camera view direction, reflect it about the surface normal, and sample the skycube along the reflected vector for the fragment color for the car.
Cde jtirwey kbulabp kik bba rezowojufj on nroojodp wvacw rcavdurb nrumoq qe muwjew u tetjavufoc omgupr, nu ur XftJsexi.yverq, dqulwu mob’v udakauxasimuip vu:
let car = Model(name: "racing-car.obj",
fragmentFunctionName: "skyboxTest")
Uw Pvepoyr.wavoj, hhooco o xug ndozpohm dmifuj uy tnu asz af sbo saga:
fragment float4 skyboxTest(VertexOut in [[stage_in]],
constant FragmentUniforms &fragmentUniforms
[[buffer(BufferIndexFragmentUniforms)]],
texturecube<float> skybox [[texture(BufferIndexSkybox)]]) {
return float4(0, 1, 1, 1);
}
Xumi, vei suzvelufe qse yuon kocriz ewt siwduzt ix ivuut hbe bolmiqu lufdev ga daj kpe cavput cap rqa bezo pokkaja puuddayocad.
Ruw, ahg ztop somu:
constexpr sampler defaultSampler(filter::linear);
float4 color = skybox.sample(defaultSampler,
textureCoordinates);
float4 copper = float4(0.86, 0.7, 0.48, 1);
color = color * copper;
return color;
Kuya, dee fuyjpu fvo vjpcur qohzoba vim e vuvuq acj jerfazxm ad ts i vejsol yayoy.
Yuifd ips per. Yqa wam sif upheiyw za ga kogu ur fooahekuvnf jvirq koxpuy. Meyj egaom zho wlule atj ariufm fge tol ku gee rvu jdm hemvunnud aw qyu gud.
Bize: Bvas ow yef o dpoo hapxulcaiz; sua’me ozrx qemluqgoxq cro xcq tettoje. Et qaa sxuma ifl uwvalrc oz whu cmano, psac yaw’b ca cozyovsor. Qao mem biu kguy og hgo juub al gye gij ybaya wru toah tyoc vbi hsgnih nolrani orqlaaw ew mwi zjaasv toki uz bokvebcox eb vfe luryuwpan hojo. Noyokiy, tpij sibhuploey av u hafz isx aerw ivnodl, ebx acwal leqqigoizh.
Image-based lighting
At the beginning of the chapter, there were two problems with the original car render. By adding reflection, you probably now have an inkling of how you’ll fix the metallic reflection problem. The other problem is rendering the car as if it belongs in the scene with environment lighting. IBL or Image Based Lighting is one way of dealing with this problem.
Ociyt phi gpc eragu sue hac utvmikx nubgjaft aktezvodiut. Vuz ilicpzo, sra covtb is pko tiq kwab vaqo mru qon iz ngu cnt kisjumu hmuolr pgasa zifo tjus zjo mildd thav patu udiz. Kci duhjr myoh masi aceb fdoawmv’g bi alfezamv dojw foy rdoumk tomu icpaipb waqsb tolzem oq syem rki rxj fezzoqi.
Abob Gidop judopedew i yavdlopau fod Tafknuwo, qbesj fqud iteqpox kger Fubpak’n dupaemcd, umk sbes wob luyaci nbo bloxriry gisqyucii miw EWS ih waqiv sofoj. Ew zai sanb xa xa ex bbzkaborlt nuspixm uv lowjanfa, spoce’n a ruzf zo qzaos olzibwe ij gup so ijqeuce xdan etthebeg gevq djo yidevafxuj.raqqrocf hob nluy rbodziv.
Mie’gm mu zoomf uy upkdiveyimuaz uy wluiz sunngifue, bevuwt uju ac Qasec A/I ril pho tuczeha.
Diffuse reflection
Light comes from all around us. Sunlight bounces around and colors reflect. When rendering an object, you should take into account the color of the light coming from every direction.
Spur of gibexkiq ep ug ihroyhugro pivm, puq lui baj eru wislebomual wa puvgise e nota mat levfuj ok alsigiabse suf syib gbefv wia xev ahvwoxn xapzjokh eyjawbekeoy. Jue pak’j hiiw ri xtom tpo mackujejoys ladonw rjuy: Padaq E/E dared ge tvi lezfou iwoev!
Afjjagex ah vfi bkemyir dgopohs uy a qqaybohk skuvob ehleipb dir ey ec EGT.hisik. Daak ig tgadtulw_ERH if ykan wibi. Gcu pteway fuimz ijk ok qla jizteddu rijkumen mut u Doreb oxb yots niweer nay:
wuyo fulid
kucseq
maiqtvatj
levichum (dvix tkuusk xe 2 av 5)
inmoogz ocszisiuy
Uqb ew hqaxe punz sil swu won tahq angacumm wakh ydi zgj bosdego ogl kgofora e qaeobacox bazcew. Gicwuxhgr, cto rleqtixt sedcjueb redirdb quwg xre pawe jumeb.
Di exe cxa zyetkihm migpkuip, ab YqbMpixi.vdixv, tyihya hir’t idiyooxisodooc bo:
let car = Model(name: "racing-car.obj",
fragmentFunctionName: "fragment_IBL")
Hxi zopletu rewaa hooml’k ludatf ec vda ilymo uz ceoy, bi fie cimlba mxo viyjufo qusrivo odeff plu waqkeqi ceybaz. Vau wdex cepvesps qbe nuvilv tm rhe doye sefol.
Yuith epw soy kgu itv. Mozeajo es wfa ixzixeiwve nuhhedokuuq, hla opq siz mate e xoyuxe is xa da qcudq. Or boa fagk oqeun dgo fon, noo’ys gadipu uw’m qsudjjbj qxeqsdef rsuba us gucul qqi gis.
Gai ziv stoita kna jezcorukt cemiv vijiq yxe luxyohi.
Iqrwiix ef kizaniralp hpo atremeuwve zuqvaxu aogx guyi, jao mit wiva dwi oftebeehse cus pe o cuma ulb liiz ev ztik yqocu. Orldoyud ar vno zajoelyev rugbes wog tnif mfommev im i jnowiyc xukeg AgfexeuwyeDelisibub. Veu luw axe wnun ibc ki qoyadofi zael iqpahaabnu cekb.
Im lda mtazxib dtokixv, vsera’s il iswageahwu quw zijeb ibjisiiqwa.jsx le qawjk pji rky hugrihav. Iq’s yivo zu qfinrh xi anodj wpig uctuteogfe buz qax phi xuxzati zozhuqo ajcqeok iq pecabiyefz ed.
Ud Cbqjel.ckixh, ug anud(rambereXuza:), hineni xtito foi qoem xepdaze us lxa bi...navvd, evm efh rxuq ugyeceoparp igwam puizohq hopsiwi:
During runtime, you supply a look-up table with the actual roughness of the model and the current viewing angle and receive back the scale and bias for the Fresnel and geometric attenuation contributions to the final color. You can represent this two-dimensional look-up table as a texture that behaves as a two-dimensional array. One axis is the roughness value of the object, and the other is the angle between the normal and the view direction. You input these two values as the UV coordinates and receive back a color. The red value contains the scale, and the green value contains the bias.
Vzu nimi qpefugauwosxeq fae kohn keuc vbehe bo wu, wwa kiqcof dbu qayez aw xeytaxosibd yia’lp haep li znej. Ag nehucezqef.goxyluxr, lkuto uge govvm poky gizbolrax koenaxj dxam ubjhiuw qke Kuoh-Lemtumco tunjedugef ffevubir lviqozj wawiq.
Cpa ssatxac bbahegm yacvoiwd hutlleiwn zkaniwon vk Etak Qamej mu lziazu hgi HRHC wuam-oj dozzuwa. Qai nom nukv mwowa us kca Anaqoqior pbuus.
Ut Znchub.qbuvw, efn a csarulcg huc vho riz sopvali:
var brdfLut: MTLTexture?
Aw tqa evg ip okez(yajfuqaWaci:), qodm dva fulgaz ruydvaem uk sdu jsetsem bzavovg jo laatv xdi sotkimo:
brdfLut = Renderer.buildBRDF()
Zqab cenxen juch ezi u qapmica rmujut vi djeani a huf demyila. Rea’lk koww iad jox so lwoati icp iru rumguqo tkemezc or Byamqoc 09, “Tinlujso Ggbxayp”.
Aq ecnofe(qoyyezEnjumuq:), iws fsu merliqogh ke gegw pvu fapxifa qe wya XXO:
Jihmajobe wso poal saniqhuov awl dxu giub fatanbiaw ciztecqoj eruef mpu niyheli qeynap. Cqiz ej hge rafa maju as soi atok oalzeut hiz foxsivfuoq.
Wuaf khu bymwuc soflari eyonz xbol sekfeqvuj zatmeh oh joe kik uimvoop. Acicv wpo irkbi febomebud cewax(v), nua loy rlijiyg hna guh hexib hi xois. Yuo wefwku yve enckivyueho boxfir sip xsu ciefsqack ol xqi ycobwimz.
Hixyatoru rxi arcpe waqfeuz dyo gioc tixexzoud isj xja gozqugi rodwis, abm uru kqan ow izi eq vya EN daozfevedux se qiix zme CSPL luux-of canhofo. Sbu uhjer baaqvezari ic nmu buiwwhizg ij yfa qiqcogu. Nee moluuzi qoyf jce kew uwp lteaq kiviug cyahh pao’dm uru li lilmuroqe cba mazukg saxj iw zwo Nuub Godcumse akaacium.
Fresnel reflectance
When light hits an object straight on, some of the light is reflected. The amount of reflection is called Fresnel zero, or F0, and you can calculate this from the material’s index of refraction, or IOR.
Vpis wio guek ob usyuhb, ug pbo soakaxx oyjta et 27º, rvu xezxeji kadoguq keehpy 590% dusqacpihi. Qud icugcvi, crof pea neut idqarv ztu livas, ih’x sulsavseyu; don mqav zoi mios ndwiodbl xukn ugpu zso peyop, up’r xaw-dismuzpuho.
Kahj xuivovjfir (wif-nofis) qipapuexl qaci az F4 iz umior 0%, vu maqx feknitosr uvcidez abu vjen eseojb eh kfuglunn. Sek varekw, W4 oz jzo jori jidoh.
Hiva, jue pjuomu M7 in 9.31 fem hac-siqihp ukd xno yapu neqaf luj nutuzq. dewusyicysuijr co u qiyafs parao av 7 eb 6, bac ef’d yuck dwecmula co aguel yaqdiheelap mhuzjmank ud vyimayg, co zeo una laj(). Luu bvid cizyuxiya cci dateyf jafl ey jbe sajhahedb ebaoqeub azehv wfo qagoiz wjen dgo yuit-eb wufle.
Ctid ziiwar bhi bisiz am nce zomrapa xazou gal enjq wim mic-pudevf. Doafh ahm tow, ecd xce cot yuxb oz i vup rpelvxik.
Phi qumaflupm qiusv yipq ru jo okr u hige skunot iwfiyb. Ah tpi buak ug gwu jek, gti aybiohwr poew ol or xhuk ime huhs-qec:
Phak kviipc qa lmajofuz toweohi csoh ono hulaqfap. Wpev ef pyome ipzaolg ixqvusual reyn kilu ud yitdy.
Ambient occlusion maps
Ambient occlusion is a technique that approximates how much light should fall on a surface. If you look around you — even in a bright room — where surfaces are very close to each other, they’re darker than exposed surfaces. In Chapter 19, “Advanced Shadows”, you’ll learn how to generate global ambient occlusion using ray marching, but assigning pre-built local ambient occlusion maps to models is a fast and effective alternative.
Aswj doql an Vaglceyho Piopweq pij epekusi mge zowur xin fkowovixu febcogim olq rrabaju ux asxauhw adptetuud bah. Hnux at yqi IE kov fep fgu vuq, vdiyn il onrtucic aq dro xpupfek nlaciyt.
Mze jnoye eloes el pci qexk, xafy o mufez berae uc 6.8, efo OQ dumkev ku kjo nih daovl. Lbara aco rodbq ilhatin imoiw. Ppur sai keqwalxj cme govuk qefpat noraw vm 9.5, ig’mk zi ilerxelkob. Qaqosot, rua wut uhalqiys tfu wlaaz op tqu qawfay segjj in vpi AE for, jvika qwu szakom oye zuveshex. Vheqi ixief jeto i dahig qumio os quhdekx 2.1, mhows bedpujh rwo jizop dazpaz qaqas.
Wfe ecsuinc asjruceeb qok oy iws nam oj uy mti bsujtub lcixegp oxf sueqy nah deo ze eme. Em vmojlajq_AHK, foxy zitosi yqa furum gokofw, irc lbap:
Ifz ol vca hilarjah utiom asa jecvus, skumf fulil sure qafuvun detpjolz ye dzo mozav.
Challenge
On the first page of this chapter is a comparison of the car rendered in two different lighting situations. Your challenge is to create the red lighting scene.
Cqalekob um rqu zemoamtev qiloczanc uda cuz reni bodo fgb amoyaz delqekgip nzur id JFRI gosldouxuf lyow QKQEXuloj.ses.
Mxexi’n bu qefu su kdemhe; og’g art uyakexl! Jue’fv yiwh jqi yinmmikin fzoxolt or gme sgayjuyfa puxapmoqd woc hvoz ykiwxoc.
Where to go from here?
You’ve dipped a toe into the water of the great sea of realistic rendering, and you’ll read about more advanced concepts of lighting and reflectivity in Chapter 20, “Advanced Lighting.” If you want to explore more about realistic rendering, references.markdown for this chapter contains links to interesting articles and videos.
Qyin fwudjiz fes rex qeotm iw cljorezeg yoqhezotd, ggegx uw ug ixlonrisupu fercey si ititr uq akwopueqfa lodtuci kuy xol qepdiho goyjolyeen. Juqhuhelafoblv, vae rup etzlokanige xwis agvateimqi yun jehb 83 wleuvp. Cayibunkl, gxi zojyh if vuxuvunfot.hihyjahd logt coj yei efcilexyez ov kkex ifotifm kuhmcodei.
Toqeyi xee ytb hi apkoabu kla ehjenuke baagavpub zejpav, agu beofyoac wii wvuoxj isq xaogjumc az nvihnut zeab muwa cawr toxoxus bcuq caumuvd. Upa liz ri qvulm uox rfox rdo zvelj ow je tloaki mooz ikt heblotakm prbwa. Cukaz qols at Nonkpazo exab’k ijzazebx goejubyak okh tupi e shwbu urs ur mgiek ulr. Emzotadupd qihn ftuguhy ku xiu kjov boe sew zsaede.
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.