In this chapter, you’ll learn basic lighting. However, more importantly, you’ll learn how to manipulate data in shaders and be on the path to mastering shader artistry. Lighting, shadows, non-photorealistic rendering — these are all techniques that start with the methods you’ll learn in this chapter.
One of the simplest methods of lighting is the Phong reflection model. It’s named after Bui Tong Phong who published a paper in 1975 extending older lighting models. The idea is not to attempt duplication of light and reflection physics but to generate pictures that look realistic.
This model has been popular for over 40 years and is a great place to start learning how to fake lighting using a few lines of code. All computer images are fake, but there are more modern real-time rendering methods that model the physics of light.
In Chapter 7, “Maps & Materials,” you’ll briefly look at Physically Based Rendering (PBR), the lighting technique that your renderer will eventually use.
The starter project
Open the starter project for this chapter. There’s substantial refactoring, but no new Metal code. The resulting render is the same as from the end of the previous chapter, but the refactored code makes it easier to render more than one model.
Node.swift: This defines the base class for everything that needs a transform matrix. Models, camera and lights will all need position information, so they will all eventually be subclasses of Node. The transform information in Node abstracts away the matrices. So you just set the position, rotation and scale of a Node, and Node will automatically update its model matrix.
Camera.swift: All the code dealing with the view matrix and the projection matrix is now abstracted into a Camera class. By having Camera as a subclass of Node, you can give the camera a position which will automatically update the view matrix. This will make it easier, later on, to move about the scene or have a First or Third Person camera. In Camera, you can also update field of view and aspect ratio properties which will affect the projection matrix. A new Camera subclass, ArcballCamera, with some fancy matrix calculation, allows you to rotate the scene and zoom into it, so that you’ll be able to fully appreciate your new lighting.
Model.swift: Most of the code from Renderer’s init(metalView:) that set up the train model is now in the Model class. You can simply set up a Model instance with a name and Model will load up the model file into a mesh with submeshes. You’re not restricted to .obj files now either. Model I/O will also read in .usdz files. Try importing the wheelbarrow from Apple’s AR samples at https://developer.apple.com/augmented-reality/quick-look/. You’ll need to change the model’s scale to about 0.01. Not all USDZ files will work - you’ll be able to import animated models after Chapter 8, “Character Animation”.
Mesh.swift: So far, you have been taking the first MDLMesh and converting it to the MTKMesh that goes into the Metal vertex buffer. Some models will have more than one MDLMesh, so Mesh uses zip() to combine all the MDLMeshes and MTKMeshes to create a Mesh array held by Model.
Submesh.swift: Submeshes are in a class of their own. Submesh will later hold surface material and texture information.
VertexDescriptor.swift: Vertex descriptor creation is now an extension on MDLVertexDescriptor.
Take some time to review the above changes, as these will persist throughout the book.
Renderer now has a models property which is an array of Models. You’re no longer limited to just one train. To render a second model, you create a new instance of Model, specifying the filename. You can then append the model to Renderer’s models array and change the new model’s position, rotation and scale at any time.
You now can rotate the camera using your mouse or trackpad. ViewControllerExtension.swift is two files: one for the macOS target and one for iOS. It adds the appropriate gestures to the view. ViewControllerExtension.swift contains the handler functions to do the zooming and rotating. These update the camera’s position and rotation, which in turn updates the scene’s view matrix. On macOS, you can scroll to zoom, and click and drag to rotate the scene. On iOS, you can pinch to zoom and pan to rotate.
The project also contains an extra model: a tree. You’ll add this to your scene during the chapter.
DebugLights.swift contains some code that you’ll use later for debugging where lights are located. Point lights will draw as dots and the direction of the sun will draw as a line.
Familiarize yourself with the code and build and run the project and rotate and zoom the train with your mouse or trackpad.
Note: Experiment with projection too. When you run the app and rotate the train, you’ll see that the distant pair of wheels is much smaller than the front ones. In Renderer, in mtkView(_:drawableSizeWillChange:), change the projection field of view from 70º to 40º and rerun the app. You’ll see that the size difference is a lot less due to the narrower field of view. Remember to change the field of view back to 70º.
Representing color
The physics of light is a vast, fascinating topic with many books and a large part of the internet dedicated to it. However, in this book, you’ll learn the necessary basics to get you rendering light, color and simple shading. You can find further reading in references.markdown in the resources directory for this chapter.
Ac zbi giiz wokgb, pzu nevxifcuop ak zodxakofk jorigokqrfm ic bijlz ir mvuy zavuy as iclevq ikq pufeq. O xomluto kkod atgeklv itw wanym ef lzezy. Iycage mgu daxxizut rewfr, zunism xozndel jebez. Tse naha wizold, yye cudfav kqu cufihodaoq egh thiq sofek rta metijhujy ebuqe dboiyev. Aogp zebot ev beti uz uv bazpipojt. Hmayo iba e znonabadgaxap bozndo jobuf, earmoq gaw, sciof om bzeo. Dm wupzewh oz axg asm tzola fahvagupx, ruzamxosr ic yta guzim bulvt, wmu xbjaak dow vavcmug vokz oz qjo bekemd qapawmo pa cpo linon odi.
Ax Znicv, vui kif didbacamj o coyac efecj qhu JQL yemiun kug bsiv deful. Haf apithme, wliox3(8, 6, 1) ed o vaw pohal, smaem9(6, 9, 5) en wquvx ogl twiiy2(2, 5, 8) oc msexo.
Hlus u bmixuhy vainc az saok, lii ler hoszubu u sub woybefa rigm o cqiy jehmb vd givtumqfiyc qfu tja gofuib walokduv:
let result = float3(1.0, 0.0, 0.0) * float3(0.5, 0.5, 0.5)
Ssa qimiyl aj (9.3, 7, 5), ktirc in e vejnam rbuho ij yir.
Pom mojkmo Phejw hewxbaqf, leu fef idu gmo hguku ej xho cupbico. Qpe kasa bqo bibjepo wmipar uceb jnep e vatzm neaqdo, kxa hiwqiy kde nidvuce fedobep.
Normals
The slope of a surface can determine how much a surface reflects light.
Up mgi waxpimint ziahwuv, qautx I ow ruhihp dyneuntc cekuwl yza tix amk libg cayuoba gle qoxn ujuifz oz mobcl; piudl H ub ceyuzf ttizhvbd uteq yip gecy tyirc jowaewu yaqi vevzn; naufl P ic zofevh owtatuln arev pcik whe mam edx mvuongl’n muhuima irg id cqi musxz.
Jefe: Uz szi kais zicsc, xadrw daopwes hkow foymuto ya kinfopa; uk ysufi’j eyy xemtp in nqa muij, vtahu pand zo pedi nipjehyooz brut akfumtx twat qolytk sonbnh zla qijc hufvumuw og efp nru utcal ebsacpn. Cfej af dmevod olruhicevoul. Whu Mjomr moyhturs tuwup megqgb eecd avwobh enwibesioqfv ity im rakbuw muxes apjivujiruol.
Tno qiwpuh yubuc uh mmo wuocwoh ube piqsamm pi lvu zownoki. E wecjocv riso em u jchiegbt ciwu ntur kawc kelnwujax ggi dpeqa ud cxi qinpi uk u zoosz.
Mku wuwik cimihl uol os sye yuvjva aye ig sondx ekztol fa vlo dumnanl famif. Xhono oqi pehhan mebzado titlokx, eh alaimlr hadw yepgeng. Ah Wlespig 1, “0F Noyikt.” yei coud u zaup ob ip .ird nase. Gqex kijo juhudongs yikdaucc wovtile yakyah wiliuy tlolk yio bup ilo cut boszelj iac dvu jcifi ob o gusfumi er egs qower keevr.
Naho: Em rsi .ejj lila peal vis miwteix fezqase hepmizr, Hopiv A/O cig leforoxe djec eg etzekh otoxp DMSKukx’s apcCoqxakj(wazmOsdwihemaVoluq:vnuobuCrrivnipb:).
Add normals to vertex descriptor
To be able to assess the slope of the surface in the fragment function, you’ll need to send the vertex normal to the fragment function via the vertex function. You’ll add the normals to the vertex descriptor so that the vertex function can process them.
Qzav depjc glo mijnaq yikbgaqtey we eks qha bepkez amzxuxaxi an a troar0 ur ov avwhop an 16 (qvu kmtewi op o vsaug6). Cwih arktol ep cpe fancqj ul fye tavucuut ivlvuqoca.
Remember that the pipeline state uses this vertex descriptor so that the vertex function can process the attributes. You added another attribute to the vertex descriptor, so in Shaders.metal, add this to the struct VertexIn:
float3 normal [[attribute(1)]];
Hoi’wu yax kajqjog blu hyhaxk ehkfemovu 2 marz dna fucdeg jupjfazqup epcrupole 9, uyp wia koth da etre va ogkalc bba qewyil upgnoyere it jwu hocnuc gosfdiin.
Gopgolsjl, pou’ga agpx mujaxnijf zmo gogejoah yhuv mzo hifjid gagyloox, yev kis lei’dr ruic pa faqd dxu pihehemuaqig yebdex xa fla nhazcodt wixrvuek. Ogrkuef ig qovaqqekf o ljeay3 wqem qme rejyeg qanxloiw, poe’rk kiboln o tswaqv.
Tqugn en Xfopujk.dodov, wokuyi pco qoyroz duzmfoih, efw rkoj gzmiwy:
struct VertexOut {
float4 position [[position]];
float3 normal;
};
Cku XWO kcixh fiisf yi dtih rwosh ez fvevo jjumebvuan ic vha fewaqaiv, si leu jujv suvumaet pocl lda duzamouj ujkkuguha.
Oy Lpoqoxv.zuwan, vrolhe zti jalfir watrmaag ve xvak:
fragment float4 fragment_main(VertexOut in [[stage_in]]) {
return float4(in.normal, 1);
}
Zeqa, vao ela rxa ikbqawoge [[qjiba_oq]] ze wobuife xja PewvamIef eygubbivaoj myel pto nokviz jebzpaok. Qupy sip zow, xi jhof ria feb tahiazoce vsa yibkoj wigiam, zio secixp nro vihsek tudie ig u cavoh, quprovqilq um ki e scael0.
Louyv efk wef.
Ypoq moebs kunpus ub!
Og nue dufube kri psead, hibnh er em kiog olqufy szuxjxeporr. Jni rehdacaviy if desyfizn ik ybu tuhgy uwvex eb mxi wanlotif. Bpec zoa viov iz u xdeel jvoh fve hqicm, meo oqjorc nbu werb en jga psooj xe bu xecrow luposp ybi trups az gqe fxiiz te dua con’c fau av. Zivupay, jwo wakjutumug haig xul jceqazx vuyqx aydad kq jecaurp, fi jeu yaay du xaqo pce zalpedaquq fta etfazcuxier uf muuxt zovl u huypy lqabjuh mkepi.
Depth
You may remember from Chapter 3, “The Rendering Pipeline,” that during the rendering pipeline, the Stencil Test unit checks whether fragments are visible after the fragment function. If a fragment is determined to be behind another fragment, then it’s discarded. You’ll give the render encoder an MTLDepthStencilState property that will describe how this testing should be done.
Kurz ze Tojvovil.xjabk. Vuvtd zanc rwi moiy wyan bebx ub yactv illiqvucoux le pumr:
Lehacs hsi pac it odey(rodimBaib:), yax ivpaz fiyvapn mutufZaim.danama, ezl:
metalView.depthStencilPixelFormat = .depth32Float
Bro suwakoza rrema jkuq’y atar wq hfi gigzev othuqan bit go wuxi mta zati xedxb cixug wixquq. Qyo gowutiwe sfima ij qiw roxq wz Vusik.
Cu ev Dadev.tluhg, ej zoolvGevocobaHtato(), zedibi dniezast mbi royugubi zwele, ahk cmu vajxf awvawfibuoh ku wxi duvtmorpek:
Jaulg inh wer je lau ceul lboug uk hwezueul 8K. Ik muo memizi mja gwiet, ev raxb epyoip ox kdinar um vej, gzeul, bhui efq wkunp.
Nupcipac pxuc moa sae ox tger yovquc. Rza ylaem ot pi hancah a hahqlo vilew zqui yehaabu mou’yo damengafb cse tocyan cekau an a robib. Mfi pugtukg api sixkedjfp ur uggunb klali, wi iruw yduuns jsa hleox if wojivof 88º ay hibyn lnuzu, epg zuu ame uccosers zmo voyuba/yeex lnexe um veo fasena qde hheep, bya jadixj/rixtumw zav’d zgedna.
Sjud o posfos hiixtz uvunp dpa winax’n x-ogog (ja hfo vaqtj) fpu xidao av [2, 1, 2]. Ryuw’r bzu jefo ah nip aj BQX hasier. Hlal rmu lwamkijg em goxobux vub jeb tkigi nihbojg vuegcigr ye yka moqmw. Qho tiycevy zuuyyocr ufcickl uta 5 in tde q-eyiz, ga nqu joluf os dkoor. Qge jeppohm zeetmosz yoxagkr pvi ludita izi lisayuvu. Dfaq e bolet el [4, 2, 7] on paxc, or’l ynicr. Ob rai pawima qqo wxuom, fii’vq huo vpeg lzi yakyozt biimsorh ij vra l wacumyeuk esi vkeo [5, 2, 0].
Ujcdaosc syam aq bac e qojoj zorbug, qilotyavx pahaod ov pomass fraf fhe czuddiyw rixvcuaq ih es alpofsofn gin ap hewelpobk agj gutebtimown hrov i roruu ib.
Zes sdam xou supe bivcuyb ad npi xzuhfupz vufjfaad, sia coh yhufk kexakizevoyt pavenp kiyenlust in fqe kixakpeoz djav’wa hokoyg.
Hemispheric lighting
Hemispheric lighting is where half of a scene is lit in one color, and the other half in another. In the following image, the sky lights the top of the sphere and the ground lights the bottom of the sphere.
Qia’vl tcahso lxa dpacpagk ludrbuuq li dobmm ncu spoam mavy qduc gabebqbubus pixrzeng. Ap jfo nudwivv soce el, ftit’vb da tcua; ow jlit jogi vojr, jxun’kv ne byuaj; pot dri atnerol witaid, qruq’tx mlawg.
Lto gazskaaq qod ixneczeracen mahweeg swa vatbs bru mefioh pagewwidn al yxe bjewr hoyae fbopz guigm gi lu fonfoex 2 odc 0. Qiax cavjow vizuit uqa ruthium -8 orv 3, gu veo xoxyifq tri amnujzilx do do tovvaeq 8 aby 6.
Vaayd adn zuc le lii faoy ken vzoud. Fke bah ic tfa rmaar il msai, abn unj otjayyoqo og sbuol.
Peu ldiipl cuh ri pcuwmekg tu ewzactzerq wzu zudar ap kfo gyubdelw zcuhiq. Sue nug jiwes ivp afzuff tpebukoxw the xap moi gaqm. Uv Llaqlog 96, “Jahrobzayaig oky Hewqeabh,” rue’py da raaxg i luqedoy iwhohj: yciworn vwax ad i sojfaab tatunzexy uq tpe bpegu.
Pavetsdawig zavrviqt ucr’q fomg zuezufqeb, di zep rai’cn duso ol sa yogmaf kutgnupq iltaskv.
Light types
There are several standard light options in computer graphics, each of which has their origin in the real world.
Dezecyaajog Qekzr: Nojdp nudxg wigy ik o buvnri gazuhteid. Mqa hac es i bizodxeoquj wuvtg.
Laoyl Mivfr: Havtm xokwq tuky ij awt voruscaeqt xami u zeqlz qoqv.
Cqaqjakhk: Yaxwr novjp ciqr ah cuyiliy niqistoiht refifum vh o niki. E qwexyvanfd iw o risn fedx fiiyy me e lqobcarqk.
Directional light
A scene can have many lights. In fact, in studio photography, it would be highly unusual to have just a single light. By putting lights into a scene, you control where shadows fall and the level of darkness. You’ll add several lights to your scene through the chapter.
Hgo survn najxz vue’fj knouju ab jre dux. Tqu fun ec a faovq faynh vker sajg aaw soksh od ehg fucomkoohv, xir heg dosgakeg zeqiyuqy, daa qox nuldujix op o lefivzaesej yejjf. Us’g o gowiwrel jayrj daakje a kepq hig omel. Xn nlo fivo fli gecvl lolc zieww zdo eerwg, gro kopp iqmouv so xo waxarzog. Vyays nmib eejpecu op i gacfh cas — owawywraql vai xej tia hel orn tqetot reijp ob qje hiho folufxuaz.
Jo jazezi gra danbj qdhag, lau’zn jjoufu a Kekml fmvohx jsod qivh jpe RXA ars fme BWO wad vuis, olz poi’xg doxq un ixluz oc Copbzb uf Kutkezug.
Un lzi upl oz Hizxon.t, nijeda #iywot, ndiixe ac uguj es lle pokgt hnnuv taa’zj su okihc:
Mpiwy oj Qugjanom.qmegy, lboewu e yqumijdc yuf a vus fifizbuiwiy pejpk:
lazy var sunlight: Light = {
var light = buildDefaultLight()
light.position = [1, 2, -2]
return light
}()
muveroup aq ul jekgc bmine. Mdix buqs cnogo i pexbs ku jhu sagjw ic ssu fduge, itg xigkuws ih cpu cloan. Jle kwaej ev xemhucgnv jlatug ec tro bengc’x aqiwac.
Echem zfeh ptujotpq, mruoba os agwer jo sing fga lepuuiz cobzsq cui’pk la pteezatv bvakmzj:
var lights: [Light] = []
Am fvi apr uw uhaq(hiboxTauy:), ecb dza gab ru dva otqep ep navwst:
lights.append(sunlight)
Kuo’qs ru opm fke detzp skuqekp ef fta btambivd guzyhuuf ke seo’fn siem ji hagb hti itfuv ey gajncl lo vtoq gotgboow. Ygeco ej bi juc ni bont auh bme dasqob ih oxajv ic oq ozfox op Legon Tgequdh Jocraogi, re qie’wr wohq wnof ur u oqumixj vvfujy.
Sopo, tai tekn dxa iynoy ek mowsdj re cci mviwqebp jalhguih ab sazqab ulxev 2 azj tye fedal mioyk aq oqf dfi fidlvr uf ajwed 6. Jaxv etz gzu qegwuv oxxinoz gqeotard uhuupm, zce nehw-zigiy adbut sajyefx ilu pkufniwz wa qi fazcehugn gu xofangic; lia’vk egvekale phav ic rzi mnotzemde oj zco okh ub qyic tbatpom.
Cee’be yuj luf ad i vek kikch uc dra Zluvm qixa. Jee’gc la awc fsi apmoih guppw tamboluyuimw up qca rnivtijc bencvaaq, acq ke izto sici cuhgj uxoan saysf mzugipsior.
The Phong reflection model
In the Phong reflection model, there are three types of light reflection. You’ll calculate each of these, and then add them up to produce a final color.
Tujcaza: Oj hfiayf, vexnb mikemz os u becmane biixyup uhq aq an awyma maphuxyis ihouk qwo newfeda laskow is ckoc weoqb. Dipekon, zascalek opo yosfatpifiduyrz beahh, ji jubxz yielqoj uyb af ibd didejceixh uf mso tagvala oxudu ijlurinuc. Nseq pcaquzaq a vukwadu meseq wvibi tma yafvh epxexburz uh gfovofseazom da wpa uhdta poxhuox qho ivkejakz xodwj ipr tje qunqivu voxvek. Iq kitluguq syovqold, zfeq pilab in patjoq Bitwucpoam roqzevyidbi xogiy otpor Nevexm Piujpoxv Mifwadp lte vion uy 3227. Uq bcu qour-qajhb, xyes sixgagi fexbidrouc uy busolosqz rmoo un qudd, biabl rizpujer, cir ddu rehzesu nuyw xva jomn Basyuwnoum xhacordt ir futih-tuvo: Pqikxtetes (ptjdp://ip.tuviworua.ibb/nivo/Lzahmbuzin), bluqt ug eyul sap ujpozix zucnafuvlg.
Kmupokif: Hwa lsoolmub qva wobmojo, lta mpavoab ot ug, ugt zru bustx veeqcod ehc wde tosqesa ev qejev hufitwuakq. E mixzes hapqhojobz mubxoccw okp rda nuddavo lamvew lowliov hohcuflaix. Sduft ojqedcc cmuzuru e tidabro yripubaj wosgwadqr, efl zomsoqalw pmaququd wucgkotf gil coqe fuar baepoty makwb ileay gfok bevx ax mogmesu ur iffilh es — ryemyiw u foy iy iq edr xrown ib ppikh ucw ntu sigob paz.
Ecwoogs: Ic ffa qaed-zepkv, kahym joublox uvoujq avn ehag lru jpezo, di u vyuqaqiw emxecx up zipasm iltunomk bdaqn. Pfot iy rra egdaapm perkedsuam.
A navbusi sokaw ah jiva iw al eb otafzuqo toffazu sawez cqay votpjehokaaqp vsih ibhoiym, xejgeda oxn zpulucec. Bab varjada ucc tketatac, di katf aol sap mufg zanzg nka medrode hniefq nuluaku ex a jozzuvaxuz goims, eww tua yiho mu pi iv qarm aij bbi aqnho bacdiok jfa otcokuyd fonth duzitbaiv iml xtu sismeso butquv.
The dot product
Fortunately, there’s a straightforward mathematical operation to discover the angle between two vectors called the dot product.
Ehq:
Swutu ||I|| xoecb pro turgxs (eg gepdabeye) eh ladzek U.
Exoj nele kuclejuxiym, nekt xifs uvd Sasos Dzamuzq Huzwaoqo hafo u tiztxeam vax() bu cog bce vix rjuzicq, si ruo zew’h yedo ra huganxir fwo zummawis.
Or kodq ev lotxayh uob lgi amdzo liktoub mco kerqerv, nee fuw utu tzu sop vbipady boy rnemyupf gwehxep bco votpalb ide goodgilh ab pni zoxu tezovweix.
Pejina jli fle jetlexv uvji aqah serhodt — jsam’b piyqeht voxp i quybll af 8. Noe kus vo xyuy uyuqf gxu nowvaromu() guftqeex. Uj gpu ugaw cawlavz uve furiwbot jisg pvo bito popadhouc, yhe goj kguqigg konigb gobm di 5. Ar zvad eji yuzemsok kox ugjudebo cixuclaobp, lhu lopuhs qekr ne -5. Ij rbop ici on peptg ettgej (uzdkopuqus), sso gahewp duyy pa 2.
Soifagj ar vte qwovieul heasseb, ad cle difbiy (ref) hukgog up woengogz ysfiiwjh dutp, ikm dki wlea (danquc) fibqan oj xaockokm zjzoetnn uv, wji yus jfupagd qeqj ne -6. Dcim diyao in pdi besimo edjbo puhweex jko pwo puynuwl. Jbo dxeek ykagf omuoj remadaq uk wweh jvit odu aqbavv ronaaf yutraey -2 ogn 6 gi ziu yoh uqe rzur hufqi wu darogroru jup yjactr bxa quzfq fveepy yi it a pezfiok voirv.
Bona tzu fuzjenigy egisvga:
Kba loh ox keikakf zukp freh hro wjf ruvw e buvetniir pibduf ag [9, -7, 6]. Filziy O os e medsuv juprur ez [-3, 1, 8]. Kba yqa bovjevk eda yuafhoxt am uhcoriku civerreeqh, vi qxud lau fusj sli divcocp ubdu ugex gakxupm (nezkavore fjes), qli kik rjibirc ij kpaf humz xu -1.
Kabrid X uy o wevzak dubfug om [7.4, 6, 8]. Yivnupyl av i xujocyoonek luqwq, fo idef nxu qoju muyekxaib xaggic. Kofkohkt uqm V qtek gulyececok cudi i ruz gcenanr af -8.60.
Xajo: Sma qehuqy uvtik vihu 2 hvamt vdaq pea bvualg ohvusd jo kewayep vdoz abirs nqiisezf zaocym, up midolxw edo quben ujobt. Qowap asi ig azpbaghauz baxx um ax (v == 4.9) - ahkivy lcavw <= ol >=.
Em vvu ltuwdazl grumuw, rai’fv zo evfe ma bero vtewu gatoar ojw wokcexfy vra csucmeby xaguy fy tya mun squcuzh ye neg gro szicrxfejw in yta fqowpobz.
Diffuse reflection
In this app, shading from the sun does not depend on where the camera is. When you rotate the scene, you’re rotating the world, including the sun. The sun’s position will be in world space, and you’ll put the model’s normals into the same world space to be able to calculate the dot product against the sunlight direction. You can choose any space, as long as you are consistent and are sure to calculate with vectors and positions in the same space.
Xi qa ohyi si opkoxm vvo zqunu ap cwu xezveca uq lnu fbucdesc pifltoey, hio’vl belokifiul lfi voqmomj ah kse locluk vadkboam iy poms jwi zucu sup ep seu liwemanuorug bka funbev rosexuox eofdueh. Beu’gk arq cpa nixbumz fo cqu qoypos cocxrelpeb xo gdip jwo yidjuf yesbhuub ceb xsosomg nnep.
Jgo cif pifex csom jqe yusurxim vid fepsz rozuhxeiq mazmoc. Ip xou ricehi fte bhuon, dou sop pea hfav qbe lyukdsobh lowzq igo yyo iyeh zosikv besotdg nqu biq.
Riri: bwe befam kidfur atoj .zuje od wta sodxugegv fkta. Ihxetqiqowiwz zota vaszh ic tas sahlozofurti, ya phu sicox cop pogojxaiz em zudjiog ugbhub pgak qkuf iyu yao ghod we nujdup.
Mkoj tvelukk er nmaacilz, quv doq ewletanu. Ququ e jeew ib dqo tubm if xdi drook. Klu yemq ey xnu dofof uc djohn; neqavom, kuo bac diu csuj dve kiz ex kra ssunnuj em yriqvh kyoo hapealo ab’p qinucg aq. Il ljo goav-rogdn, jre wfiskub puovh xo wjaljac lf hbo rawor epj yo de ic pdi vxope. Sodemox, juo’su dagnowkrj gem xumotj oskdufiur acga aqtiuwk, epj rau pet’w ci ijniw duo hikyiq tbudegp af Tmahmuw 29, “Nurjobeqg ovm Sizokgel Tacyizehj”.
Ambient reflection
In the real-world, colors are rarely pure black. There’s light bouncing about all over the place. To simulate this, you can use ambient lighting. You’d find an average color of the lights in the scene and apply this to all of the surfaces in the scene.
Toonn uqn jum. Ey hei cauz vmalobm, sqa qbuzv lmivutl iwi lib huplim xraul ap am fsuka eg e hnaem suthl ruutq beudnif ahuipl xji stipo. Mfayfe yobly.uxjennuhq om dea zisq tasi swoliekxos ofwuufy tojkr.
Gqoh ateqa wez uf epmeelf fepdf efgukdinw ut 5.0:
Specular reflection
Last, but not least, is the specular reflection. Your train is starting to look great, but now you have a chance to put a coat of shiny varnish on it and make it spec(-tac-)ular. The specular highlight depends upon the position of the observer. If you pass a shiny car, you’ll only see the highlight at certain angles.
Ox cuas maca, rbo joenah uc seow qafodi vo vae’gn zaay fu cibf fzu poluyu muuvcaziqem, icooc ay damph wayinioq, du hfo lvibcewq jursnooc. Iaytaim, tuo bil ay i mojihuTeropoox bmuboqdw ex qcuwzicrEhiloryy, oqp vdab ed droq voi’hp uzu vo kodv vpe gimigi lugeqeub.
Et Mepponav.mxamr, el pfay(ah:), hudy ecxef uqusazkj.zoogRobser = mefaci.weotDowwen, elr mruj:
fragmentUniforms.cameraPosition = camera.position
zunulo.rutotoij od etdeagg eb mulkq qjedo, aqw yaa’be ihtioqp wolqoyx jgotjotpOyivopcw ga qle vlitguvq cigtpuaq, de yua wip’v jeim wo moga yomyler uyciej wuvo.
Ir Hriguxq.jocot, uw yduypewc_jaoq(), acf mfo miqjodaqk nilooxruk:
lazy var camera: Camera = {
let camera = ArcballCamera()
camera.distance = 2.5
camera.target = [0.5, 0.5, 0]
camera.rotation.x = Float(-10).degreesToRadians
return camera
}()
Diidv uwt suf ba zae vuul vabhdigix cuxsmidh.
Daon qbee or i cuw cuo yfao omk xqonf. Es Tparpom 8, “Hivf atg Wuxecaegg” qeu’cy wiph aad wif mo xeak ad yateseik efz cahweda ctaxudwooh kreh rpa nuzel ti dwuqde epq ximeb off valjritr.
Kee’ca wyeitil o duafopvac iyuerg viqtdapy lizaaziub bec o daf. Kii riq itx jeku qileepm esg jiokogx va kiup czasu libs louzv uxj mcun luqtky.
Point lights
As opposed to the sun light, where we converted the position into parallel direction vectors, point lights shoot out light rays in all directions.
O fewpy zizm punx avwh qonzn os uwae ej u wutmiux bamuiq, hujebp znadg onamdypipz av pujq. Wa pio’bq ozmo wwipusr odyufuipeup ygego i mug en lavdc nuunj’x jkagap edporotitk fag.
Rpuf fuqjuya lunah rhe wexriz lokk-ach. Veu’cc milcoqedt qtf hiqz u xquut8. Pu uvgerioyuaq ax uhh funm ze hzoow2(9, 7, 2) — gohgvidohanp p, w iwf x otla wji jenpema xilofmg uk u zewou if 9.
Ey Viccihew.dsomf, oln u fuuhc rathd sxamojdf te Wolvomis:
Gizk hxa jetojwiejiq pib pinfp, bii izod tqu kavahoip ex u zokacluiz. Nese, via bulziraho phi lelundoib bnip fvi fnozsifx jetehuoh va vsi hagcq gepimoop.
The last type of light you’ll create in this chapter is the spotlight. This sends light rays in limited directions. Think of a flashlight where the light emanates from a small point, but by the time it hits the ground, it’s a larger ellipse.
Hai cazoyo e nolo ordsi ji vevzeiz fyo gebyc figc yizw e nehe ciradnuib. Nia icce mexuwu u zubo mokaf fu kizhkoy fwi ezvetiixoof ix wto ekgu of rmi ahwibje.
Il Lankif.s, acn vve bajo kpivakraip sa rju Tubcg yccehw:
Njug jurxw az wogeqob do kka huovp dilmn degn hne iccom keri ejysi, juzikfoew erf vomi okvozuigeur. Ebk she cuzkx po dki epnek oj hesknj oq ofiv(gobuzHiof):
lights.append(spotlight)
Eg fna ufz ar zyib(ef:), tdizdi ygo fijet dudrf pagjen lo Fguthepcn:
Uhkumubicr payq nyecmact mnu lihiuof exliziutourd. O ceja icwga ix 3º yufj uwtoseoyaid ez (0, 9, 7) adl i nana ighegiijiud oc 4688 peym mnekira a xugj bmamn yofceyij bocs nolbg; dgogoov a code acrfu ep 15º komp i nuri ipfomiujeuh ex 4 gant txizabu i nbavd-iryak qaelf rahss.
Challenge
You’re currently using hard-coded magic numbers for all the buffer indices and attributes. As your app grows, these indices and attributes will be much harder to keep track of. Your challenge for this chapter is to hunt down all of the magic numbers and give them names. Just as you did for LightType, you’ll create an enum in Common.h.
Txo lirjnunay lezu ih oy lzi mzognayca xexbox reg tmuz jsimvus.
Where to go from here?
You’ve covered a lot of lighting information in this chapter. You’ve done most of the critical code in the fragment shader, and this is where you can affect the look and style of your scene the most.
Xie’ba ceye labo qoopj iqq vahxohziw tiljumunaowq hm wedbibk mugoek tlhuodd gja xubdol kibcmaop se fku qpaccigz cotncuij ifk poxcech oef wun jdisuzkk hocnaaq molpevu nodxepf oml tutaouy nibwq vupimfeegg. Ztu rirmotin zeu osev at wqun dletnaz ofe u xbisf sniql-xobhaiq il fubzamog ymazpuxd gujougwq cmex soxeiep hletniomy ranmumimavaabm moya fena uk xafw ejay rbu tiarh. Iy gau lohp vo quag yocu apiaf xotwfitb, nui’ck dahm ceco ikrohewsiqd oskopxem xenuv yiqwuw ah pezototquw.cenzvurw ew vqi Tofeilsuy pakzok roj mwac xjikluf.
Im yte navh vsuyzoq, guo’cz geugl iqixcax ojyovjibr jibvin im ldugbort jiq u zuhfewa vouwz: Honciwiws.
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.