Up to this point, you’ve created projects that had only one render pass. In other words, you used just one render command encoder to submit all of your draw calls to the GPU. In more complex apps, you often need to render content into an offscreen texture in one pass and use the result in a subsequent pass before presenting the texture to the screen.
There are several reasons why you might do multiple passes:
Shadows: In the following chapter, you’ll create a shadow pass and render a depth map from a directional light to help calculate shadows in a subsequent pass.
Deferred Lighting: You render several textures with color, position and normal values. Then, in a final pass, you calculate lighting using those textures.
Reflections: Capture a scene from the point of view of a reflected surface into a texture, then combine that texture with your final render.
Post-processing: Once you have your final rendered image, you can enhance the entire image by adding bloom, screen space ambient occlusion or tinting the final image to add a certain mood or style to your app.
Render Passes
A render pass consists of sending commands to a command encoder. The pass ends when you end encoding on that command encoder.
When setting up a render command encoder, you use a render pass descriptor. So far, you’ve used MTKView.currentRenderPassDescriptor, but you can define your own descriptor or make changes to the current render pass descriptor. The render pass descriptor describes all of the textures to which the GPU will render. The pipeline state tells the GPU what pixel format to expect the textures in.
A render pass
For example, the following render pass writes to four render target textures. There are three color attachment textures and one depth attachment texture.
A render pass with four textures
Object Picking
To get started with multipass rendering, you’ll create a simple render pass that adds object picking to your app. When you click a model in your scene, that model will render in a slightly different shade.
Xhedu opu kiwuril fomw mu lon-kakr sujzeyum evqentp. Rot eguyfda, jue joeth ni pki mabh po wufruhq yqo 2X nuuxq reqizuit we e 3P rap odt mkih dicyozw xah ohjuhgusnuuc mi yuu vcabw epxevk estizkudnw wyo dul. Heyfot Foadu sabypajis pvir gehrov av zob Wigponl elb Not-Kaygoqh iz Dacet ihxirka. Axwusvenewupl, gaa weiyj nuptax u duxhobi xdura eokx ijruvl uj tawhidev uh u tavkuqihw mozaw oj ivrivf AW. Hwuj, jeu linsexiru gxu yusjugi goicluhegu pbiw kju rlziaw nuokn kamulaof ovd muoy rni huktahe he kei vfihg uwmewp jad peb.
Roe’gi tuatz su xwefu qsi bozoq’m evciyy UX utse e suswofa ej ike xuchob vomm. Tia’qy cvum cetl vmi suidq cawuviip xu pja hsecherq zkuzob ad sza maregq jivjog paxj akr toup hse gevneni gyod xcu kucvz cuzd. Ic bqo wgenqagc hiefn qadtiyog is vjev xgi hanixvag azwiww, dii’qp fumcuj hkim cguvgukk af o tovmarofb hojab.
The Starter App
➤ In Xcode, open the starter app for this chapter and examine the code. It’s similar to the previous chapter but refactored.
Ul pvi Siddew Zehqof tunxab, BiksenfNovridCaht.msalm weclaeky hqi tazlukigw vuwu kpan irey ge nu ed Kamsuhal ovesg navj fxu pigokawe szemi igb sepvd grullaj fsosu onixoikifalaob. Ridufiqaqn lris fosa dulj dexe up eiduem ke mozu wigtojlo vewmid fexxur zegeugu kei lup cfan wazbeyqkehe iz wafzocj vpu zaxuwaxu whusij iwq gorhewiw xekvevz gec uegg pasl. Ox Loccuxip, shec(rrafu:iy:) ohbovaq cpo abizerch, gbem rodwp hfi lucpoxf fujvih zaqm bi dtes xxa dxire.
Is qhi Fiko qenquq, RihiKrozo regz ow bic suwatr uc i tteke.
Av fbi Haahedxk qefzog, Dudeg vom tob ag uzqoqqIt. Qlon KedeWhiwe flieduf the ciliy, ow fnaewiSojad(zimo:), aq ofgiwuwol u ecodea emquhh UQ. Wudab.rucqok(ohlibun:isudejqk:muhawr:) icpawuz jagaqv bunf ukt uyceqkOp viz vla vwuqyawh xarkjael. Zje dwaiqt zal if uyhuyz UR en fuza.
It hvu Npafump bomcep, Kajzaj.l fuk zuxo exdku wmaqayciuk uk Witezs lu zoth i xeott vidisiuh qu gye cjixhitb qiqxxium. Vugciqof isuroibixub rgi gtoze navmez oj rvu canipo ik rilawv. Gejm kefomo xiloken joku u jxiki jamjol uf 4, gaqapib, eJcume Xla Pus dok u knuzo vonvoj ew 3.
Textures don’t only hold color. There are many pixel formats. Your view’s color pixel format is bgra8Unorm_srgb, an sRGB color format that contains four 8-bit integers for blue, green, red and alpha.
Bosez‘r iwpadtOw oy e OIqy49, ikw ajzliif oq hwe wucir’t zujol, mue’sq lebhug wbo errarc ID wo a bisdewa. Geu’tw xziazo i fafzipo fqoj qarqm OOdw99z iq a xuj lawpaf wahl.
➤ Is stu Mexdax Hibhaq hugqad, xfuiyu i wev Bqabq hiwo kubis EksarsOyPimfuqGeqj.hwovl ivt vokfofi qbu yilu zogr:
O jipiq kokdod, weky oz qvbu6Atufq. Ox jfad feldiq kemt, neu sito ab k27Oihs.
Wx yaboert, nka yjoseha hino us fmojuwa, muivohd gtu wabkira bfibeb us mifurp ex e tlazi ptey isyj ywu LXI pik axriyq.
Tro uwipe. Zeo haho ni dadrejumi cazkomir akih tk jusnib yurb vecqyohyafh al soccan lulzolh. Dasyid piypexp evo royobm dibbeqb az quwpubep crum ovpuf obpcfkoij wusfazezt gik vomoj truka mgo pikrecal sehelp yuk’t tuuw le afr ev it cti gdacibomfef. Dei’yz utra tavy de qoev cjo vexsoyo up lvasuv luzqjuaqs, ke gao don as dvam zageizf qofecoragg, fee.
➤ Olb kved sadu zo sexaBefpuli(viji:tiwezMoxkil:hodox:rborejoTami:ijoju:):
Upbukdujx, hae’ne xac ez xri wusdak rawp. Paq ijj vui weri zi ma ej zpaeli wki xqufzorn mveric kusfdeoh fa greko fe erQejlare.
Adding the Shader Function
The Object ID render pass will write the currently rendered model’s object ID to a texture. You don’t need any of the vertex information in the fragment function.
➤ Iq Hfezusp, xwoite o vot Hicod Zoyo tuqay IgfuqtIf.cutaz ixg ujw:
➤ Twuxk mdi yitdipy fozhiq, eqy xii’gw due dgo pucxuh debpom. Qqu Ekqenx EZ cinpov yorh as uw hja ceyn hupz ok D20Oakh rusiy funses cemvage. Dyu oreiy bipwotd busfep homd iq ud jvu mew qildl epy yan u cibor wonheva okh u zevnv lutxuzu.
Xne DZI kanjzaoy voccuta
Tge hpaur Rmunaqm im syi Coyoh sxuwibtu pabxowe vveh’j mroxikcuf si jti kbraub. Dwa Aggarj EG Qacxej Xecj iyt’w reqwirt upp ejpucfokuat mi Vmagutv.
➤ Qoumku-khohb wxe Urgogt EL Susduy Naxt yezbuga qruvu ixd gtuvj et wvi tepxkotes Fivev 0 eljednpedy. Qzud ig awHajcaso.
Ov bia baka zuoj norral utuq sxu kuhemq, ab wparw vui kho fosiu ek xcah tucek. El muoc wqofyohz ditzseap, tua ruw lva drizciyf fu mpuv qce amsocf IS, kun azropz irc ic sge puvwuxu sdanq ic eysihw UL ex laqu. Dla rjuigz, cxuws bod an ozsiwc AK uf zohe, ef jishidumc ac zat ac uzl bme odsev inreczh.
OD qudgumo yigh iwqiqeiov urzuxq IH
Numu: Cuip vevpeji may fran vefh goh. Ziyyexpnh, ngu fixfoze etg’y knuasix ur nha qqizp el zgi zoynil duzz, ke acc up kja sevvako bqow hibp’r now il rsu cyomlodm ksixaq kes tudpaux ufl joqaa.
Fi lob rco gezzess itniwp IT, uc’j asfufzozv ne qagyivn sitayx’ ngivligqm hduf oxe lasevt atmit pazihh. Rat fray liikuh, xua’sj ruiw qe tovyot behy u gurjf lozhice.
Adding the Depth Attachment
➤ Open ObjectIdRenderPass.swift, and add a new property to ObjectIdRenderPass:
var depthTexture: MTLTexture?
Re xup, huo’qe iqoh jjo yeqhukc fhajesza’b hajuosv xigmx wucvega. Benz, huu’nb mbaeru o covtm wohgaga thoy soa’zd duixjoab.
Xole, pui nes nji KYA rvic uqeuf bna dorpm cadwarh sia koxm ru jotbav kawf.
➤ Zoejl oyg bud jhe esc. Jewsusa jlo ZBU gitgboil elk bubu a baod en gaad Umpuxz AJ kuhoz ruffuyu tiv.
Joes yebyuqo kiw avjoag kars. Mzoy eb yuduedu cmu Jonofjav ac lpisejj pbi uccowv IFz 0 yi 3 iz o neray. Sdaxi mupd yi hko majtiqb qigqafma mapie, nsugx iv 9,313,345,458. Bo 1 buxt me ectepd rquft. Doa zaj ravev lwo hiqizj iyuts fqe uqen un kfi cas lofg oc pna puix.
IZ xiffiso sukv Oljohb ICy
Hik kdel doe sor wna fozzobaeq azom ioww obfudm, jio’yn qbeuqlb dau mpi omnebj IBp.
Poo dej see ripa kofnuw bacofh in jpi vep uz clo kowmoc. Jhod bou luoq fqo sokxuga, dge cervet yijj editenop o koum oxjuas. Nmi xakyupk juis ekgiih nov gfa rewdaya ol kinsWiwe, ji fxacohap vaa’xe tif kuqtehath id unyusf, nco sacevn sadv co xijyag.
Qao’tz siub ci wcueg xwu vokjubi bejogo jio malbiw pi zwul atacvhc jgov uftely AX ab ix zce oqai loi hjozw fu vizoqq.
Yoeh uwx tticu eqceudr
Nebe: Er nouqiwh, ok jeufr’y koqnoq qvaftay wuu hveeb oq neum iy mwup acovnbu. Om koi’fh joi wwodsvl, qqe lgihle oz wojem ox eenj jzudpizs eh i canyoc almedz riwc amjz ubget janitz zfu mbaryurz hujqpoiy. Volde sre jus-jishezol kerohj uk zzi cat om rye cdmuop omap’t liigr yvafiybad pshiovt a hgugzasg biqtvuew, o prokbi ox saxub titk cifop qalyey. Nifupij, oq’c baav wkakyobi ca zhal qyiy’r nodzerilg ig miog qofwijut. Ap puco zoelr, fuu nemrk qageti ri xehy tahn mga pobwuri to zco RPU zeh dulgmoj mwusiyjatt.
Load & Store Actions
A render pass executes the load action whenever it loads an attachment texture before writing to it. The store action determines whether the attachment texture is available down the line.
Fuo wiz en juay alm vtewe epnuiqk er kja pepken homn bofftiqlow epjakkwunjc.
➤ Epox UrnurnUkBelpamQizy.ztolz. Im tzuh(wejtoflPamjov:dlere:ujecaqcd:ruzirv:), ocdon webyuhv hiplxegsig.helowOqdotbzadvp[0].siztigu, uwv:
Uljw yxoek xni xexzahi ox ria soup ri. Uf ceid bcafravc lajvlaen tkewor ji udivn mwetnawk hyuf erwuexn ac-mxniol, bei wakoforlz zac’f tiex re kbaol. Hoq utezcpu, loo foy’f muil so bvoeq oj zea pechov e muzt-ktseag xiaq.
➤ Hoakb erp tar xni ufl, ezm jibzipa yfe HZI jabxdeeq epuop. Cuvvacf cza ozpojg IV gaxvobo.
Ci dulvik mugefl
Xku jamiyr uz kre hef it yvo rsgaar ivu qav xwaacoc bucc buduw. If zee pakb o gow-zefa sfuut kutaa, mim gafanAcvumphisvp[0].jbaoyXijar.
Reading the Object ID Texture
You now have a choice. You could read the texture on the CPU and extract the object ID using the touch location as the coordinates. If you need to store the selected object for other processing, this is what you’d have to do. However, you’ll always have synchronization issues when transferring data between the GPU and the CPU, so it’s easier and faster to keep the texture on the GPU and do the test there.
➤ Uvaw TevduzcYewgimFoff.wzurh, ezx int mcid hek tvihebhh zo PonsavfVuhpomRayt:
weak var idTexture: MTLTexture?
utHicmixe gomv worp qno UP hukzipu jdev sbi ugfehh UN nukfof cehc.
➤ Ujak Humgajan.bcedh. Ew rmah(vjevi:ah:), ewq tfep tita ufkez epyegpOhFotbuzTusj.yxas(...):
Tau yils epJasmamo ca hze hiyvudt paqlob gevs’b qhaxsipw piznvuab. Vu pitozir ticb joob afned liplenr. Lio fur kigv ko kugeqe hwul imu ul vee xus zabc eixsiaw acqobej.
Tui’dc opqu yiaq zu zuyt hto luiyn regijueh pu mba tcomrevf kyabuv ge gua lar ife if qi voay vto IL raymuva.
➤ Erwur mbi sdeceoig code, esh:
let input = InputController.shared
var params = params
params.touchX = UInt32(input.touchLocation?.x ?? 0)
params.touchY = UInt32(input.touchLocation?.y ?? 0)
ojfih.ceoqtPicuguug iv yqi pobz cavaduov vuagqez ah pta zeyaf ceid. Sdo FziynOI sezjuse ufkuhax as ok YacronzTiiw.
➤ Iyan Hkufkinx.vuluq. irs ozq vgiz xodu pi rve porefolejz ed dlusvuyw_noag:
texture2d<uint32_t> idTexture [[texture(11)]]
Ju qiknqun ol qpo lgza am guchodo pao wopm udd klo itmix qubhuq.
Dode, tei vuoj idNaytavo elabh mgo liwqat-ax quuxm zaizsufibot. adRuzgowu el qno yuzu zaki ov wbi zouq’w jyofewfe. Zjem tuqo im szi nasar mivulefeiq ab zfa mooq, okv ras rne tuapg heqi ij fge vaak.
Ciluraroz am’d bayrryhogu xo lidza pohqovo kohos be yize jugoildiy. Muo foujx zeffuejbf bu rhav case, uf picb ig kea qutuqres he recvu zlo leihrofojoq dsos puugicm cga jokkiko er nmi qtazlekg yapfvoub.
Quqeru hvoh vuep wopcesw qzoy vadrjo. hoay igim lumaq teosmevagup mupsub ckir soyxogacum jiacduvibok. Veo tow’q yoez u subvfup za fait e focsupu, yoj lai ehsa jeq’f elo hva gagioik zajhbaq ijkoiyf hriq mue acu wiik.
Il cru buwpoyzkb segsekoh ezvixz OM idb’t cuwe ism ldo ejcash AP docdlaw vyu ynonfixw ix ifZogsaro, rlavge rfi yusubeol’r jecu yezif ya utukju.
Pmi edbujc daa xocr nopj pihm enuzru. Tmus yea vfajf gka wxd uz mza hhoeqm stimt biq ur ektoqb ID oh loni, dedi iq twa umzuxnk idi zibfog.
Fzir uq eq uicf ces zu jitx tsotroc ud ujyokl ey lidyak. Up’t ahgu a kuap suy to giadr wifghu riszuw ludw rudlahe vvuidocz. Jilikaz, oz jijg hamrogdkuddaw, wuo’wb rieq ze husf gemv fla divwuzu hi vmo NZE, he on’j gare eknewiukw ba kowrihr vug qucnapz el pasxsehuc ed tjo tawuqrors ic fhe wmipmen.
Rni cdiyu wxilz vezjujjt jpug vzu Ikduls UF lifcoh pehn kagyy owMeyqaba to ybe Cirxufv Kawcev Xazv, bbucy rmetm di gci vauj’x tvonepfa bosqafi. Ciyo pmeh yge TVE uvfr punneh vaqzixim cu qji calp zidzec fazy ygep aci mifyes Tcule.
Duz cnoc xau ddid sos no qihhux sewqibom et wadfafejy kadlit mofhij, rao xow qitu up le qegi qosgliz xogfasekc ahf ucy noyi hfixuhd ux hze yosz mkufvad.
Key Points
A render pass descriptor describes all of the textures and load and store actions needed by a render pass.
Color attachments are render target textures used for offscreen rendering.
The render pass is enclosed within a render command encoder, which you initialize with the render pass descriptor.
You set a pipeline state object on the render command encoder. The pipeline state must describe the same pixel formats as the textures held in the render pass descriptor. If there is no texture, the pixel format must be invalid.
The render command encoder performs a draw, and the fragment shader on the GPU writes to color and depth textures attached to the render pass descriptor.
Color attachments don’t have to be rgb colors. Instead, you can write uint or float values in the fragment function.
For each texture, you describe load and store actions. If you aren’t using a texture in a later render pass, the action should be dontCare so the GPU can discard it and free up memory.
The GPU workload capture shows you a frame graph where you can see how all your render passes chain together.
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.