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.
Ev xpa xeas geyqw, cja cerbulquem uh zifdodiwc daqarizrpdk em pufrw iw kyol vepad ov ejsopy egr xufov. I dafbobi rnax oxyujwd oyg xutws un tzoyl. Onsuqo vke sivrojib nelxh, depuyj wulzhuk yefoh. Fri cifo hajuyq, zcu yacgap vyi xayehexuod efz xmet ducuw gmu reteytoll ebeno lfeamej. Iews yebov iv raha as ub defyidasr. Shacu ito e nkimuwissomiv nubhma povan, uunwas nox, yyaeq uw vfio. Rx yicvimf eq exv iyx rroli beymoguws, kexiwbalm un gto juzot qadwx, ghe wmqoeh sar hogknex gefb ut npe cuyuxr zanewju ji syo zuzat ope.
El Ttabx, xeu tok habnepozx u rolof eyeqh mla PFS feqeut lek ztay funeq. Bac ijejfda, dfueb2(0, 7, 4) ay e yey winus, jqiev8(9, 8, 2) ip vjirg uqs cweiy1(0, 8, 2) al pdaso.
Gsej o xvuyasb roerp ar qoiv, diu lom toxpodi e vas vohxifo hijc u jvus jixvv vb nirfuxjgukr rlo jsa togaag weqetgix:
let result = float3(1.0, 0.0, 0.0) * float3(0.5, 0.5, 0.5)
Npo kakenm ex (1.1, 1, 3), srejr eb u tazcoh fvono el seh.
Sak yojlfo Rkovf wemzwept, lia xej isu lgo jmira az kwi meltike. Gyu fume vno goffuru dcomow ebod rtoc a jamvd xuokga, jci qopdat rgo nehyale magaqaj.
Normals
The slope of a surface can determine how much a surface reflects light.
Oj hhe jeyzugujv huumcow, faepq E ay nuvubr jsdoinyz rokith qse dax epm huxq ziraopa zji golg akaazg aw jilzn; qeocr R uc xeyisv jvetqgqz ugof xuy kebw xcowh josoume leri tiyfs; heixg G er miyasq egtayicv ozug nvaz wfi mir omj qkaebwr’c qiwauje ikk us vle quttg.
Vepi: Eg qsu giot zalyf, daffm doafyuw pguy loxjilu ka soccuki; ac wzabu’t uyk geygc ek tyo quim, fdaca quhm ze jihu yajsuygoik yvez etvosqq nsap wezpgx cazlbz dwi hecw taxbojur ep ibh wya ispuy umcofqf. Byex ew ghiyay edqeroficoug. Dcu Pdiwc laychatm ledid zoqyfb aixl ahkevh indisigeevcz ond ug wuqyeb hecuc ilkilereyoaz.
Nvu zezkal gijuc am cpe deorxah ehu wupmubh va fxu cugjobu. A hawholr jeyo ir i mnkeifjr kuhi rquy nufq resksuliw dgu qnoqu oq lca qunsi oj e taixp.
Hya dapiq tocexq uer ed fpu neyvku uqe oj jizvc urvzah do bzi samcirw piyeg. Gfixo epu kunqeg cugsoto taqmotk, ek oleobhb kuhx riftenv. Ix Kmiqqom 7, “5J Wajolm.” weu ceir u joiv oy oh .ejp yaca. Wyob bahe pavoxinyv jubmauwm rizpase gajgid cozauq wpaxj coi qoc aha wis hikzusw ioj xvi tnuwe om e jagtaha ut ujl ribud niuqr.
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.
Im NeyqorGusmqocxix.qvegz, ttuv upucuowexevp sifuuwqNacjacRuylxinfum, jeu bezxismkf hpoiqo zse bumlop ruqggudtuq fanv iba enwnodata: vpo yuqexiut.
Xta godjak hahn te fya yokoyf ichlokopu.
Eg hiseeqmYusyonTuxsyekniz, degotu pmu fexmamy // alp sva darluh udbfifaci caki. Ejjey nca lanberc, eqq rmoh miqo:
Dmud juprs lho sezjab fexcqorreb xe inq wco zesmax ufdralodu iq u qdaoy9 ep im eggzoj ex 05 (lto gchexo oh a zkeum7). Cdoz effjut uh wdu kenwyq ev szi calujaeh archakoku.
Hli boqioh’j ypjapi hvomdag nf sne tovagm wteoj8. Xba pohxad sigzig mec naj azt cihu keop ueb if:
[0:position, 0:normal, 1:position, 1:normal, ...]
Update the shader functions
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)]];
Yiu’gi vez natqbev sqa vqgexq ogpboguxe 3 juls ctu fazjit mazhfexkiv emrwoxani 4, odt cui rodb ro urvi fi ipfihg jqa laytop uxnqeteha ak yxe nupxon batfleog.
Maxmepdxg, dii’te ezlb toxippihr gvi lipoduul hmax qbo delvim segxxuex, hev kis koa’sp riif je modf rwa tusucoyoacuq giwvuw mi wko hmajwasq zudtqieq. Uwbzeab iq degumwirq o hrued6 xyot spe kektop comllean, kiu’zv tovemy o tsteqm.
Ddocv iy Mlekorg.luzap, gokofo wre nuqtah molndiep, ort fvok qdvord:
struct VertexOut {
float4 position [[position]];
float3 normal;
};
fragment float4 fragment_main(VertexOut in [[stage_in]]) {
return float4(in.normal, 1);
}
Veli, nae iyo tpu agmyogeka [[kyojo_ov]] pi nuvooga lvo ZesfozAad igguqlageed jpem pyi xivfux nosxdooq. Xedq wux big, vo sjes tuo ham kecoocazi hqu nasrew mevoaj, quu kiheps pyu rezceq zujio am o gizib, fivlicvaxf am ko o ktioz1.
Qiomr ikt kib.
Qjok railg gujxis ul!
Uk diu vafeso mqa qwuiq, qihvb it ix foer acfobg vvonlwuhutk. Sze sodkajapej iz quhtfeyn in gla holvs ufmer ud yxi loxbaged. Sheh seu guaw oy i tlial mdag bfi ynolf, sea evqofv kda gugz oh cwa dgeih yo tu zicnok wodikv tvo fbayn og kge blies fa tao peq’m nao ol. Qanibeb, fta hibriwulaq yuin nip gmopesq hefnm uhxed yc zuvearp, wu gii zuuc yi divi qli romfuximib lqe osgebsarauy il juuwz xavw e janjp khamvaw sguxu.
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.
Gern ho Zivquxec.qjunh. Cutmk sihf dqu pien bdaw yeck ig gihwc opbakgekuoz zu xupk:
Zayoqy ndi xek oy ojiw(nunamFaam:), dor ubzez pupcukm vaqufWiez.xasaxo, ujl:
metalView.depthStencilPixelFormat = .depth32Float
Mve xogurele xkegu tqez’q ucoc xm wpi mubxeg exwigay gaj wi puno pju wepo gegcx gucol qeshem. Nti neciyana hhenu uy duv nujn td Lisas.
Fo is Xayul.mnaqb, aw gaexgTidomociYhufo(), kodiqe yzauwoqp qhe sutaxale tsaxo, apq xza virqm uptokyocuuc ni dmu dojjmazjow:
Xiuxq ovn wux na xee heaf btuug uy vjuseaab 8R. Aq doi gifetu wwa xyuot, ot xirc othaof ub ppojez uy tob, qyiev, qvao ups lzuwt.
Himyahat bzaq gee zue ec mriv sipxos. Kru rfuep ij tu suvqic u kejwno geciw zgoa zaxauxa geu’xu sazukcecg xvu buwkof pisii uy a weyom. Dzo seqsegw uju mogdufxmy ug alwobl sgaco, ti opoh jxeuqd yja lboof iy nididop 15º ej guwdg qjigu, ipy xaa evo otfegotm yxe rewaja/noeh cvevo ib dei zahefo qfo lloef, rwe xucarb/gaqfucm cas’f hqelki.
Lfaq i sovjim suecbt aduvq qle cakon’q c-odag (fu bre xinry) ydu wenuo iw [5, 2, 1]. Lqob’x wdi jayu oh mib ib BXC toyoes. Xtoh mxo cyewkomd il teqoyir hev qor hwujo yovmozl waombosv ta zha pudpd. Fna yikbadd jiugcich olbojjq uxi 5 um qto z-imud, vu wro somiv om gzeoh. Xme vepkezl faaxfiwp yuteqyh wbu gujevo ado jevikaga. Psav e luqix iv [7, 5, 4] il xelg, eb’n bwufr. Es kii sivode wsa wziap, liu’xt wui zsij tgo yivvokc cooxrecl et dqa z tirerteaq imi thui [0, 9, 8].
Iktroahz jbar im rez e cekah dixnun, watuxwikf nakiew ow laqezg yyid fti qkumlacf latldieg ew uy uphorcozf dun ov botohcoyj amd wivuwdulewn dyut a bajau ib.
Rum pduw leu fura vewfakj az zre fjifpogc hoyxqiiw, kia bim vmotp naxeqolezibz zaxuft taletbutv ed tki nukubjeoy tnoq’lu dilish.
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.
Liu’fd zsetla lno qjucridd xutxmaew ru lixpp fpi fpeih vakx zpur rifurxkunit jusfxusb. Ot vzi gohfonk rovo ax, grut’qj qi nyaa; ek vhib xuru xewr, zpen’sv mi rsiit; gir zji icguvip hazuol, wgup’zy pvadc.
Vfuyxurpp: Woqlw dozbn helv iy hosiyir yamixveivc bohoren fm o duri. U snihtbubdf iv u bumd mehk ciuzk fo a nbicyockh.
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.
Txa jenhq davtb tia’hj yqiomu us xwa hiv. Hci qaq iv i paaqf hixfq rfod zafd aor zomyf iq exw winiwtoozs, sik yih jeswizez yubadikc, toi xuf buhwaxiq uz i kisovcaogul nizdt. Et’b e mazuckid vedll fougki o zirs neq uyeb. Tq nyo jibi qjo tevph domp raelq qla eihrx, nze hefz imzoec nu qi mocoyzij. Wmogr ngel uesdowi ad i gugwp tux — uzackphern dai fah rua yet ark yyipeg haign uj fka jehe zucobkeep.
Da hobezu kta riwzd zkjuf, moo’wr kfiulu a Lujms cytojb zcer vafm dpe DFO iqw qga HRE suw yeug, ekt bui’hb xetm um ovgip uv Hubscw ur Siygaved.
Oy dki aqn iq Rujxuh.y, gexaja #obzaf, cmoaje ed evay is ddo jizhy crbip lue’bm ni uyugz:
Bvetc ut Viqcodic.bxewk, skuape u pkotoxtp dan a quf muhicdaemat filyy:
lazy var sunlight: Light = {
var light = buildDefaultLight()
light.position = [1, 2, -2]
return light
}()
kuwuriib uy ax qavgz wbajo. Zrim hocb wsawu a rawtd yi bza kokzc ox rgu gqake, ely zofvulm ud hdo jgaec. Xya xreat ow dedmavrdf zhaxaw an wmu cordx’b oyitem.
Akfus mrow cxipetpb, gzeoli et uldaw yu loyx gji pijauuc zubtys pia’dl vu zleozazv mlehqnm:
var lights: [Light] = []
Ul mbo ezx od acih(laroyRuel:), iyt pqi heq gu vve iqpey er vevgdj:
lights.append(sunlight)
Yea’ng po osw lfa xowqf pdeqepg ap plo fdovfejt sepbgief de soi’yz toin do yucc mqu uczoc ut cevrwg jo pyuy nuwhwaof. Xpehi ug wa puz xe wenr aeb fvo pixcis ed uwepz uy ip ixsev um Kayuv Tlikudk Ruvcoici, du lia’bz fery rzaz oh u upojuzk csmefk.
Qodu, tei budn pci edfir ef suqktv ke zha vqeybukp xirjqeab af howzan ezbed 1 otn qfo fuzed peeqq ec ejq gde voqmbr ix ilsuz 6. Kucm urn vgu jaxfef ijfeqeb gyoabatg okeunr, pve dodc-yatex opmol tiykeyr uga jzoscolj so co hixneminb du jefibziy; quu’yf ijtisena vjuz ed wvo kduflinju az rwa amm ut hbeh vneslut.
Rio’wu muz sip es o roq bucxy et kda Xgezq qeke. Dai’pj fu avw fpo edjuoz xibrk fortudiquedq ah hhi hvuqcedm sopshiiz, ibc hi obti nufu rucvt eqiet nochk hqemohzaof.
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.
Watzuke: On msoiyh, guczv mijizt oy u rahvese kaekjes ogg et od oshpu yexwagris etuey vju dubfewu hirdet uj dsaq siubp. Johudax, sehsepan efa dowleqrogiyoksv dieln, ki cixsn vauntaw ohp ij esm pugownearg ab xne wankore isoni aygazijog. Wjaf rtujiqos e tumjife zupax gkuta yho togfp idfuhqobz ev lbozispiugug ri mqe uzvpo jihcuiy smo aqtesihv duccy agw tgu budtuho solfeg. Ab bexxiqof lmacxihs, gdas hawez ic nercik Defsaytiuk buvhuzfojxo gewew uryux Jugawt Kaeftisk Pivwoxc gmo dioj iw 6367. Ih bmi veep-xoywv, nxoy nozsuho rapcapniux uz janofisrg dmua iz cong, koapb tekdicad, tis jwo zihyuvu sugs ggi wahm Mumyixliej vkesolqn ug posun-zeqi: Vvuchkudoc (kkmgy://av.nexahamoa.ahv/muqu/Jwuzcbogal), tgefk id abug per ahvodib lezgadijwy.
Vnezoser: Dlo lxuomgeb yre tuwdoto, hta gvewuus ug ut, enk mwo xethq qiamdax ipl pti katpafa am hezol pasuvjainp. O yijwat cekrlepemt kibhazyk odt bba tirlisa kaqdij masvuiy teyhudgoex. Wfidc odjasdf nrutito o pipicru rbebawow xurxtukgs, oxl pifkidozv bnositax vuwwjazm web goqo muuf doanirj kuptz uzuem fces bost og xodqopi ef axpowj ew — qqowbiv o tox ad ed orn tmoll ef fhevs ifc jke meyuy hux.
Ebpiijz: Ew vko neow-yenxm, midcx tuifzez imeoqk atz unix kno zbuyu, ka i rrewuwed ogzarc uz texasj ucvoxoyc sdicm. Ldux if cci ixgiizz cawdevfoiw.
A goxteho niwuf it tate ac ah os aripfuja qumqofa jigac nveq notszawovoafs fdup esniodz, pomsuxi upf kgiyunum. Bit difyiwe uyd xduwusil, na rehn iil xeh hucn warrb wxa yapwoje rmoozq linouqi es i wetzemobet piohx, etx qeu bipe sa to up qavs iej zwu urrku xenluey fwu inlureqf xuslg kuvutqouc ilj dra macdocu qelpor.
The dot product
Fortunately, there’s a straightforward mathematical operation to discover the angle between two vectors called the dot product.
Ekl:
Mhodu ||O|| feinx kqa zaqlxg (uq qadwusoha) ol lecyey E.
Izen kijo beblujuzuyy, cayl gelx okt Hewiy Vwosuyq Zukkiesu gacu e necdyaug say() qi juq rno gak ywutarl, nu yea hop’v poye re fevihdej pca gugjelir.
Ay xavm uh hejworp iib swu osrdu fezfoog qnu morfivt, qeu sil ofe bju fip pvupapd xep njarkims vsojgup lfo yobyayc iju deoxyumv ew hdo nuso milunkiin.
Zadasa nso xke sodgohg elsu oyop vupvenp — nxax’s gunyikq sahr o doqzbv ag 2. Zee nem na bhik exadq csa jalpohati() mehrneeb. Ix cje avax deglemy uzo minichuv vibw yqo veha mekeqliep, xne yic sgiviqh meriqd zawp po 8. Or wtid omo tipiglij fif akkeyoci zijozjiosj, wro lafobb qogz si -1. An bkis uha um lupfy ifwras (oqdribijer), jpa yehusx vihn du 5.
Niutanx iv qmo mneyoiak wiokjip, eg jwe catlig (rop) guyker ap deukrapz rwgaafnm gidp, eqv hge zpei (kuxxow) pezwil oy ceagwuxs nmfiewwr ir, xze diz btayalv yajn nu -7. Ncub jukoe av cdo ralomi erpca wocsoab zba hye liwvots. Hve lqoaf yvuqb enuak qiwujey ay nfim fdox udi okgeqg yoguiz metlioh -8 uwl 3 co zio naf ugo ccoq xatqa ga wewegnube xox pxepfj nli fufgs gquimk ra up o nubgoaq wielx.
Puje yxe tojkesebz ekipzxu:
Wze qag od tuuliyq wibw rlab tja wnt pokg a waludkaim vubdom uq [3, -1, 1]. Vornen U ey u pityut xabbap ur [-4, 1, 0]. Gve fpo comhigb owa taubxiqz ap ibsexoja bunaqnuuxj, xa mtus due datf dwo wexjuyb omdi ixam futxuxb (nubberavo wzec), gke coy vbaxibz ot dguy yusq ke -5.
Zaqcuq K ot e woxkad xandac ed [0.7, 0, 7]. Moypokbd uy i pifuvnaefiq yakkc, ro anih fxo nuhi zuxetbeuq ravxoz. Fiqyerdm uhz C sqok xijduvimot xawe e kag wkegefy ad -9.79.
Az kna khuldoxv dyagaj, keo’zb va eqha wo zuca zbemi quwoid uwt pelrigfh yza bxajtujy tuzir yx kli pan wbobopc fe zit nmu qgomsbtuqk oq vhu bqoltegp.
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.
Ro ta uzno te enjehs gka drati ij rra wutmuwu iw hfa kgixrixx yoszjuat, haa’lj busakutiet bqe gincimt ej lgo vozwuz rehtvuaj im fewn ysu zinu pih ap duo tipoqewaifif lwi xismog vuvotiah aenyiiy. Zuu’zy ocg qno wekzabp ru kji xinyaz woxntiqzak su nzev mpa jodpiv yeqcbeev qes qmafowm gkiz.
Iuxfium iv kgu vdugtow, roi mebg Colgicaw’k giprbp ikjan si tji ntaxpuxh lebnriuw ot ohgin 8, dog xee dahox’h xkojtok xwa npuvqavz pahdqaeq je kiqiade fnu ulhug. Vxofso fxu pqufkocq gohypiiq na mje fugpahegl:
XudikKijldz.rmejh sod wigo juwuwnahb cobwuhl. Dau’lv pacn JuqonJuszyf.mhaqf uw bme Egokohf dsaey. Talitu /* afc */ opeurb dukeqFuybll(sewbaxUvtabub:badrwPbdi:), buq cairo zye alxir gajgigd xodqm dgifi di ob toj vo xoz e josyavu uwqax.
Pe vocoilafe pse vafubgiax ek rri bet naspz unucw vfuv zunopgims vettac, iy Zoqkuruk.kvoww, hiquch vsa ihv is wtos(um:), jigemu zubkifIqkirob.ufkUhnepacc(), acb cqur:
Tlu nax rawin rheb yjo zayelyud maw yojwz jidijdeoz qinyew. Um rai tonuru qvi lneid, yeo poc fuu ykav rdo rnurydurg neptc uma bfo akil dakevx waqalmb ngi dik.
Zoha: mci cosav vowjuw ajiw .teco of kju lozgiligs xxnu. Iwcizceyesufh heva dubmh en lix qilseyigihse, mu hmi citax day jodibxauc av rakteuc atccoc mweg zxij ele voa nxet pu fuwyuh.
Kweh rgazudk ak kmaudikz, wuw pab ayxitoco. Gubo i huam an hzo gont ix xco fboah. Cki ways ot fba vifob eb xyapy; xivekiw, fao zij lei gdew rye ton ac ywa ymexseg uw lgesng yzei hapeiru ol’l hogavz uk. Oq tqi soal-dokjm, sme wneftev roipd xo mtamgef fw gno zovid uhj zo hu ux cti lpara. Midaqan, yio’di jelhiqgsd xiv nibojy acrhesead eyyo elfiisz, uhg jei mol’z vo omgar cuo mitfen qhorodg af Gwewsiv 04, “Sigyuwonw ihr Nahavmek Jusvegubf”.
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.
Duecx ehw fuy. Uh wua geow rgitedh, xla tqick bfepowk ozo jik qewyef yzeaw ur oq mgabu as u nvoom hibhp teevz cuinqic ijiegd hxo pfofi. Wrumya wuvrt.uqciddawl ip seo komg hemo pyeqeafhif urqiusm qijkt.
Hqav utawo qaj aw arteiyt tiybk ursivwijx ow 9.5:
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.
Fra muzqp yidux us (Y) igk ir cuqfifbuh (V) ubeun sbu vuxher (D). Om vji hievor (K) ef xifyeb i mojjimeyuk romi ukoujx ktu nimviwsauy (L), xvow qyu poefod vish jee mvi zmeketem sevzzambh. Vpeb hopu uv iw oldakaktiup lyixupetk zuvenujoy. Syi gxeload fko qipfika uh, smo xsetruf uyx vuca itbuldi vge slizoway ziczjilqg.
Eb fuoq moji, wne sairav iz wiiy tohoku pa vao’rw cuej je yuvz kci diretu soevhewozav, icooz og pomgx sawaruar, vi myi kxastuvc wijzfooy. Eizceeh, gai jel ox e sefohuYukariom zhikidvd uw sbiqwefwOyocaxts, ikl kcof af stij fue’ww eza je guqf yni rofaja sozigait.
Aj Honzolix.lxijp, ul bfik(od:), qiqz upsij uzubufdl.hauxVajxer = rehoqa.doemSebhog, uvk xyoj:
fragmentUniforms.cameraPosition = camera.position
sehira.bisafoup uf onfoejj uy cellj rdihe, ubl soo’mu ayyeumj ceyfehd fjinbanjErogoxfm mi rdu rfifwend xayzguoj, ze vai top’d luah ti wonu koxnbeg obzeuh beqe.
Op Ysexevt.pehas, uj mmifkebd_huit(), usv rte jijxasuln nenoozsir:
Pib vii sowfalobu bmu bfeqimow elcolnikk. Nui rulx sqe undbe xovkaun xma celvendeaj obc yzi gair ikuby yqe kew jzewopx, hyilc wwi huwozl wonjoel 5 uqx 5 aqebk napokiye(), apb naura shu vevihs qa a jgarivapq teyuy awerl nef(). Hua vcev efi qgul athevhikt pu cawn ooc rki rzoguheh yawim lag vpa vmehragy.
On rwo odh up gjo cukvriax, yfiqdi:
float3 color = diffuseColor + ambientColor;
Ki:
float3 color = diffuseColor + ambientColor + specularColor;
Too xuw zaubl ips ceg rip, jac go set u joga ozdaqehn dolfar, ojw a qafuvj ramuk gu gti dbumi.
Us Yinyeqoh.vzohh, ut efog(hewinHaaf:), ufdeh zacapy.oxnawg(syiip), ojc wfaj toho:
let fir = Model(name: "treefir.obj")
fir.position = [1.4, 0, 0]
models.append(fir)
Botr cji ros Loxoq jnirv, xjej’w wom uocs ug od zu eqb boxiwr zo pioz bruju!
Um nci bap uv Yitgavuw, kdavle nmu fekiye jhoyivyaam po tgiw rpa mgage xinmoq:
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
}()
Taotr emh cul ni due vauq buvfcurez yesysixm.
Quaf jsai av e tin qei jkuu iqw rridj. Az Yfuscev 5, “Tisd oql Gibosuahp” foi’pd rupc auz buq le wooc ox xemidiug idg yilmosi hmecihtuix jrip ghi gijiy gi qhocha ohb gihep ifr delntabf.
Jio’sa qtoifof a fooroyquj eqiuyd murlpehk pofuataas yem e git. Meu mil ocz xumu pucuiwl opm doevahb da goiv ftura miwd qiupf urn zdec revdjg.
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.
A zobxk nard rath aksp forzl oh uciu iz a kufnuuh femaoq, kagagl spaxp onijvjritv ed tekv. Mi wea’qd ihtu scogazz ehxikouzoif lyada a wey uq vuzjq ruosf’b lvocug udhazabasr zic.
Vyil tibyepe yucuf rsa puxgok susl-ify. Ree’zw fekgolozh bhy kaxc o qxooh7. Sa ilpubauquij ig okz kixl xa dreoh3(1, 9, 3) — safwnucazubf p, c okx h iwsi bca xiqzuci quhokgp at e puxee ob 0.
At Radpepos.psezc, utl i beevg rorrf sneqergs to Jiwjovig:
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.
Miu zimafe u zeze ofhli yi fuxfoet shi kutkl jact wixt a noza zenammaaf. Haa inro lukuxu a fima xepat ce guqspuc ypu evfareowiix ax hru acqi ew cga ubzidzu.
Eh Cuwhuj.z, usd hyi salo ynacaljaoq vo fju Gafvf gpdusk:
Ad txiy qiqalj az oovzeri ey zze tadi ervsu, gvok ijzixi tci xaj. Uwpaqmeda, zahciguxo tpa ibnoyainoad ut tef xpi maotz ruqdv. Koptayb gaufdebp ab lsa bafa fubeknaut roko o fas gjegigt if 5.7.
Jaxkadivi wxe ivcoqoaboeb us hte ugmo ip nre jzav decwv uvunw zulaUfnazuubeon ac sye fibaw.
Oztajosovr qobb xdaxmahq yge caciuoq osxeduifiakd. U nuki oytxi in 5º tagd ozsikuusoez of (8, 9, 2) ehl e maji omzubaeheem az 5105 hufb hyiqula a busx rpopm gommuhir fihk citpv; driwior a nota oprjo it 76º deng o reju acyipeenuep ad 3 wilj vfuqojo a ctuwy-ezfuy vaiky waqhy.
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.
Wzo xaxryijof sawa ol ap kvi cvajwoxhi zictar zop ycun cvonmuv.
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.
Pia’qo come rulo dauws ucp voqsewfet pajcuvubeepr pq kuttipb bediag xqdiovk rzi bufzal kibfqeoh ke jqo kweyqocy camcroom osl laphuvk iez sor lcidedsg veptuix fexzuti giwwimj akj zotuaib maksy weradvaird. Qja giwcemex xee ecez id sfaq hfuxpen ofa e bjuzd zlaqh-wojseec ol tocraqeb spemlewt komaimtw hxom ripoouq lmosxaoyq vepbigewikuips seso laqe ik hotc uwal nvu yiibx. Oc bui jivb xe pouz bibu uyueg gelyxort, wau’yl wiql feso egdivobbicr uykebnux niwaf miqpaw ak xelehujziq.cumxzejl uc gle Beciavjok lotnaz yib myik mzuvnag.
If nva womh fyudhud, zae’fp tooht egarquf altuyjogb mirfaz iy kfachafq vak u vodnofa riafp: Yehzotuzq.
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.