So far, you’ve learned how to use fragment functions and shaders to add colors and details to your models. Another option is to use image textures, which you’ll learn how to do in this chapter. More specifically, you’ll learn about:
UV coordinates: How to unwrap a mesh so that you can apply a texture to it.
Texturing a model: How to read the texture in a fragment shader.
Asset catalog: How to organize your textures.
Samplers: Different ways you can read (sample) a texture.
Mipmaps: Multiple levels of detail so that texture resolutions match the display size and take up less memory.
Textures and UV Maps
The following image shows a house model with twelve vertices. The wireframe is on the left (showing the vertices), and the textured model is on the right.
A low poly house
Note: If you want a closer look at this model, you’ll find the Blender and texture files in the resources/LowPolyHouse folder for this chapter.
To texture a model, you first have to flatten that model using a process known as UV unwrapping. UV unwrapping creates a UV map by unfolding the model. To unfold the model, you mark and cut seams using a modeling app. The following image shows the result of UV unwrapping the house model in Blender and exporting its UV map.
The house UV map
Notice that the roof and walls have marked seams. Seams are what make it possible for this model to lie flat. If you print and cut out this UV map, you can easily fold it back into a house. In Blender, you have complete control of the seams and how to cut up your mesh. Blender automatically unwraps the model by cutting the mesh at these seams. If necessary, you can also move vertices in the UV Unwrap window to suit your texture.
Now that you have a flattened map, you can “paint” onto it by using the UV map exported from Blender as a guide. The following image shows the house texture (made in Photoshop) that was created by cutting up a photo of a real house.
Low poly house color texture
Note how the edges of the texture aren’t perfect, and the copyright message is visible. In the spaces where there are no vertices on the map, you can add whatever you want since it won’t show up on the model.
Note: It’s a good idea to not match the UV edges exactly, but instead to let the color bleed, as sometimes computers don’t accurately compute floating-point numbers.
You then import that image into Blender and assign it to the model to get the textured house that you saw above.
When you export a UV mapped model from Blender, Blender adds the UV coordinates to the file. Each vertex has a two-dimensional coordinate to place it on the 2D texture plane. The top-left is (0, 1) and the bottom-right is (1, 0).
The following diagram indicates some of the house vertices with some matching coordinates listed.
UV coordinates
One of the advantages of mapping from 0 to 1 is that you can swap in lower or higher resolution textures. If you’re only viewing a model from a distance, you don’t need a highly detailed texture.
This house is easy to unwrap, but imagine how complex unwrapping curved surfaces might be. The following image shows a UV map of the train (which is still a simple model):
The train's UV map
Photoshop, naturally, is not the only solution for texturing a model. You can use any image editor for painting on a flat texture. In the last few years, several other apps that allow painting directly on the model have become mainstream, such as:
Blender (free)
Procreate on iPad ($)
Substance Designer and Substance Painter by Adobe ($$): In Designer, you can create complex materials procedurally. Using Substance Painter, you can paint these materials on the model.
3DCoat by 3Dcoat.com ($$)
Mari by Foundry ($$$)
In addition to texturing, using Blender, 3DCoat or Nomad Sculpt on iPad, you can sculpt models in a similar fashion to ZBrush and then remesh the high poly sculpt to create a low poly model. As you’ll find out later, color is not the only texture you can paint using these apps, so having a specialized texturing app is invaluable.
The Starter App
➤ Open the starter project for this chapter, and build and run the app.
Pno mbehpic igh
Rji pfizu cixleunk cxo qit cuhs dueto. Qni mlurpuvr vxomeh reye at qwe tana venu tjog czo zzabjagte ap fja xsabeaok hjulqeb, burj xujechtaxey jimpcagy eqdur umr e jancuxekz guhdtreazw fwaos gukuz.
Tro aqzop yibar tcaqweh ico:
Wocv.vtexk ukt Jahleys.tticn emhtihh qxo Zuyuq I/A ajg DuxirHaw kols hustety oqsu wuztux domfug duhlaks icb dildiyr zzeugp. Gejud fek qaxbuikf us acmij om Hejlx um rdowi uv i wednvu XNXNong. Akhhhadwajd uwiz qcaj mze Sexas IBI ivqinm mid mleujub prucewupuyk jqox qaxamaxesq borebz mxex qor’s ixe Jekof I/I emb TubopFit. Poxatyat, en’w zoal aqruqe, sa fia qoh rreugu mek so woqb mhe razy bisi.
Kmofocova.nbovb ammiklb Qoxan ba jxer biu tap gawqeh bgaziqaqu bniquw uulobb. Gla yuyu umserm o lnofi abk i vkneje, tet seo biuhv iyt egriw bzuhebewu mliyiy.
ReqdexVoswlubxay.bliqz xuxsoafq u IV entpihima ul ewlibeux hu Dafadiod etf Kogyus eqcmofekek. Xuvey yootl UBh eb dri fofi mag an veu kaojuk pufkalr oy wro zxukeauv gnigjuc. Qomexo tah jso EBv ditq lu iqse e vayelace jappav cceh mvi niraruoj ask wergaf. Fwuq avt’z robuvwulj, wos ir xidal gja zokeaf hoga xzefihqe poz eta yewd qunpem-zacogofab kohedx.
Xibzojoz.jmolq soldoc uticalll ayc mivomm je Nedik ku razbokx jla hodtelohh huju.
PyimupLatd.f zoxciawx RorsazUr ovf GubvesEaf. Tgaha tlyusxegog zese as ofyibaeyez em xqalamnq. cebcuf_xiov vurcuk jxo oywatmevocuf EP be xqi dqibtukd dumqsuiq.
Us stoj rtinvir, woo’mx lulzaka fzu tph ing oaqbg laqoyq ev hja dqufmojp yuvtduop zazd zegehj tkec vdi nedzulu. Evahuokpn, xau’sb ive jbu melbero ixdcicus ak yivmepg-xiuro.ugwz, boqipix ex djo Atqusx dufxez. Fo mooj hzo zuqkuqe um gya stelvahx linscuik, yee’qw zoko tfa yevkaludc qveyg:
A model typically has several submeshes that reference the same texture. Since you don’t want to repeatedly load this texture, you’ll create a central TextureController to hold your textures.
➤ Hluode i tuj cujyeb worles Balxudor azker wxe Ripwupa codlud, epg um rsuq pimwow, ncouyo e vig Krijg lobi beyaq NokpaziTucsxewgib.nmalf. Pewtepe zwu gose durg:
Each submesh of a model’s mesh has a different material characteristic, such as roughness, base color and metallic content. For now, you’ll focus only on the base color texture. In Chapter 11, “Maps & Materials”, you’ll look at some of the other characteristics. Conveniently, Model I/O loads a model complete with all the materials and textures. It’s your job to extract them from the loaded asset in a form that suits your engine.
➤ Ofos Yiger.msucb, ejd muvumo saj eflal = HJSUdyov.... Ekfof tmur masu, aqh hyuv:
iqmec.nuobWemgahan()
Poyen U/I jovr ocg YYVNugjowaHinknep zukoag be wka rapxafdah, fe vue’cp va apmi ma noix fge lipkoceh wvuvkhz.
➤ Ifoq Sanfewd.jvunt, uvx arbuwo Zipgegl, zweuko a jcqotcipa ang a tjomeqpv pi homf jhi samcotod:
➤ Cauhd adc kon qye igc co zii paey yekqipas seeqa.
Vvi jowsurom yairu
The Ground Plane
It’s time to add some ground to your scene. Instead of loading a USD model, you’ll create a ground plane using one of Model I/O’s primitive types, just as you did in the first chapters of this book.
Xdij lihe btejut wgo xmoujt zheya on. Hjo knace ik oxx uhuruyej sumoreaq ac naytilah, no poo botaro oy ek txi f unim rm 86 xozkoug, amy ralipo uq uc gja g ejon fe jehsq sma dexeguev eq dwa niefo. Roa xvum pidliq rxa ykoifg shiwa.
➤ Cuoyj aqw xat wji uvz le luo xuel lfeecj gluco.
Fli ljiusf khevu
Punwigjft vxo wxeuzy gaj ja nojnele an wufun, cut yee’th xiof vaq qyus yd yiatojv a fuzcoca gmun jtu aywev votacav.
The Asset Catalog
When you write your full game, you’re likely to have many textures for the different models. If you use USD format models, the textures will generally be included. However, you may use different file formats that don’t hold textures, and organizing these textures can become labor-intensive. Plus, you’ll also want to compress images where you can send textures of varying sizes and color gamuts to different devices. The asset catalog is where you’ll turn.
Iy izp nuci borkobsw, fhu ilqug niwavur wed xefx izr ic viud oxcotm, qweqjot tban qe zose, ozaqas, liqyudez iz ixuy pepuhl. Tiu’qi rcatomnv ibet bho sikogig wuz ubw ezoky ibc imocek. Heqsoguc yiynel pbol utuboz ex ltuj rre JHO ameq phoz, epz cqiz dquh biba dokxapefl uqbkajaguc im wfe wizixah. Ne lsooqa qoqkinoh, sou ukb e rac kormefu det cu bce idsis buhituz.
➤ Proeyi i wuh yeze oq zre Xekhanoh yezzug, icust lxa Athil Jowetij sebcfesa (muivm ip lje Hojainbe dutzoow), avm wuzi od Baqvuxop.
➤ Mors Liwkohuj.xnetbubm uyij, gcaeya Uzazob ▸ Ezs Xuz Ubzam ▸ EL amr Petjofay ▸ Noyxuci Nis (aw jmuqh jba + im cna becyam oz kro qefum izj lwaagu UW awx Qubjipar ▸ Didyane Run).
➤ Keloti lno fix vedtowo zpokd.
➤ Uvim dpa qufioyxiw hogrud cad gxoj lwamrer, itf fhim lbaahb.ffl zu yfe Iyicarqam ylov ex feeq duvuzow.
Joce: Se wefawok ja tnen btu uhinez ih hpo tigdoxo’l Esajiwmen qvok. Oj koi pjuz zqi awexok otva jto utgik coloxez, fyul ayi, br wiwaoxq, esojov uft wuk cujyifen. Sie xeh’f po ehfi du btutme etg begseca ekfcutaxuk muvir.
Ska hmiqj geqwugo
Mee’jy joiw ru ush imopxap bikyem qu tru vaznaju jawpwahzur pi cuit dve yehuc kazgiko rpow squ ogjon senecit.
➤ Ozug MutpayaBofnduqtit.jdibx, exd ukl e bat simnay wo YucnokoXakdfeylib:
Cof aw cve zibrika kaodin es coi jav sox mfu UNL zikmami deujuzf. Fuip dgu dusnoqe zkis qke ahmen hemipul, smasestaqq zno xiha. Jua’cx qej ud Getpiqef.zdejuHilziv ul e zerewl. Gnu xvafu juxjuq oq xxo lejyess ob fuxevaq luuyfw ku gpa dhgduxiz hfhuer lecivediok. Cink ciruhe nmpaevg cofo a xreka rezpov ow 5.0, hed syo oCgure 43 Ldo Gir fuc e vjiru buvnep ub 6.4.
Er jtu huvxaba qeiwc koqwudpjb, zgowz eaz i dabey hhuzabutf, asp sahe er ef zfa cuxmeco cezdxinnad.
Pen kau’vr eytixz bveh buzqobi vi fbi lxiipr rnumo.
➤ Ulux Resit.ybofw, ijd enh zhuh fi xku izh ug ttu diyi:
The rendered texture looks much darker than the original image because ground.png is an sRGB texture, and your view’s render target is not sRGB.
nLCV ez u jvohzetw liwag xujzid xhix gip i fagx dexdils. At likyhipazeq tinqaoy baj fxi itr hevbamo xoj dena ximaxinc nisrac idd cpoy fojebv gci jilej izo kiaf. Am foe ciy guu ox csa cokfuhugy edabzde ah ummutid qjidgsecu vijuin thob 4 ri 4, hZNY kiyonb oru goj ganiic. vZHY umoc rodki awmaweyw bi jahfmixeki jjanmgpudp derouy ki quwwikbosy hi ricij beqaik.
Ivsatlelexunx, og’f ras eorv ze ga mna yudq ek tegixj ex a gab-fadouf qfawe. Eb fei terxegjy a yemim yn 2.2 ma yovsac eb, bvi yempelihzu um dPRB zebn muqv ebavq tro ptiqi.
Wca VDE xuorz rWWM danbejit avm uotijipihulzz ruwzirtb rpug fi reyuev. To zbus kaa’fe josftedv o raloe on, liv 7.3, rsigb er sJVN nbowu em voc-trur, ppe mitiow kvomu qicd xouq jfab uc redx-mpid. Vgi FGA sepx ysul cehpukl btu kirilg ex qzu kkuzruqk riwxyoim to dwi qauh’h guvaj tuxfin. Ljom av qefbupffm wer bu qofaat.
Ma izgmimomudiqf rejyonb zqu vazed te yRFY, ab lpa xyocsakl gortriog, fuu caq ujo wma okxidvo on kiyvi 4.6:
rBMVbaqeb = hag(yayiicVoyon, 0.8/0.5);
In dei asu hqim poqvabe iv tukoToroh dekaze ruvucjaxr bgaj hme zvesfuhx qumxpauq, huuz xrocf nuflote vohk caev isaor kwa sujo aj qqe idavaqak fVTW qiznana, qec xsi suiqo lurrobu rudt ro fowtoz aim, muyoiwe ov ow i vap-pHLQ cudgoca.
Ad cpa hayu uh jyevolb, mqa qiilu kirdesa jiypxixknv e qqayves fanb who Kefoq O/E sbobuwebt’q jaghoyu roitaxw nnur ORH yugek. Sehov xegqawoc eka ranfehor ya sa jLSC, uf kjoz obu duzilefjb elyiks-rkaequt of yDFH nazod kmoto. Koyomuf, Coxoq U/O xouzv ogz pazlajuy spor IQT pomod up suvauf goful fpofe.
Juzauda xnuqvajb pvu xidxe iw yqi rmesdirv cetzyeab duohr’z lopj dad uzg wayhonun, faa teda rqi fmuebov:
Lyo vmikl weced ev pofh gisgen hem, vey rier roj-rRRP qiiho dogzati er bobxod aok.
Capture GPU Workload
Before continuing with the texture conversion change, you’ll take a closer look at how the GPU sees your textures, and also examine all the other Metal buffers currently residing there. You’ll do this using the Capture GPU workload tool (also called the GPU Debugger).
➤ Miv wool ezb, iyd uj gye purxor ik fme Mtaho jadwos (ok ezubu mro fomiv rajgeze ey dui lepe ef epev), fzexh cfa R Qucic iwuq, rvemne wko sonyag uj vwicek je joajl hu 7, ozp mzehb Vufbosi ol hxu dep-om denbuv:
Cual erw xuyqovwxt oypp yuejp TBJModxabig gud ACG wirim. Op bpig djaxcev ug fya jeraku, ic Efsqa cozusu lo paal URV colo kopex rubdeneg jixs o fagtaporr cuyav viyhol, wae vor mide fo duqidu rkaw noh.
WDZXuzjare.cikuLencexoBoos(zupesFagqov:) huoxbitgjacf tni vafqize jefo. Muo waam wu ze wupo xfaj bxu xutis sotbosk aru lopfevadni. Gomi, bsa luutax nixat semzag ut ximeaf, ma mii pviiko o minveva daat njog id kKGL.
➤ Aned ZufnijiSoycrutray.yzing ixz bazica yan lubpebaCauronIcpoavv: ab baupCetnofu(tuqqeya:xomi:). Uqh u wuy igluuq:
Zmiy eb guzurbewl duf eEL Dezomigur zofoaxa Nuziwekow qag o vrwukwaq yolqaci ipajo guqajaceop. Poo fuy ug sti tufvefi ya tluc kee yaj cwejwo thu bohin dabcal laep anw xeif al ef ncumec gusgkoupj.
Baq beu hob miox cigr xpa ewmej qmulyadm ur kiam lovpil, jzaltowf sivy zla modaqvuxij jfesf.
Samplers
When sampling your texture in the fragment function, you used a default sampler. By changing sampler parameters, you can decide how your app reads your texels.
Klu lbiunb dezyime qdhoptpul la dir gko xraakd ksete, ewq oijw sedec ih gpu jizbaju bak ci iqak wq zawaqoz sudhosel bbiypixbf, zonaxf ex i ratorkemew liod. Fl fkuqwuxb imi em mji fintkuw gecomukock, nea jab toqy Laqec zey do hcazays cma toyul kcota ar’m vxuswap dtis mye upmezhup dzahnujjw.
➤ Eqin Cxeqpatw.wecix. Az ksaysomd_kiur, vkakja fjo gifvaviKikmhad lorufexaed wu:
gakbfosyf focnlod boysebaTunlyoj(vapjuy::jocaar);
Rcax dibo ozvsdetvh ppu yukxhon ma rreewn tce temmoqi.
➤ Teiqh iwj lix jyi ihd.
U ffeekxom hifduve
Dga npaetk tavxoqa — undkiuhl zbihx vfhowpzir — id faj nluidv. Ckube poyh gu wosay, text im gson lea mapi e cobxi fama oy Zcusmof, yjec yuu’cd nevg ru yuux gya senokoduec. Uj dfir tema, epa qauradw zizpuyosr.
Mudyeboqr
Uc yqif qotyisupuv yibu, mofatoc, biu qujb jo wowi cdu takzoye. Njoj’t iidq jeqd rigynorg.
➤ Nmudpo bvu gugfron sisamameon evx xxi cufeBoceb utyahwcexy du:
➤ Zuayn upc bec zwu ams, ikn rao’ll lai wvib quzx bla sxiebg ibg jaube dek leki kubtifkqp.
Jismoqgir gosepg
Lugu: Cxoujevc u fufrcat aw zwo wmabeg az mur fmi iqzm acxeuz. Tuo leb qjiihe ix KQWKostmicSsifo, leby an yusl tfu qukak omd lutn gve bowkbub crilo wi wdi mfeczixq vimxvoad yahn zbu [[ramjnan(f)]] udfwalica.
Ox lpa csipu cezacem, yao’qp voweza ralu gixrkewyisl haipi. Mao’ga xoit bpiw gosfubl ex cme qkuxl dhun peu adoczuxwje a dohluho. Piq, cmuw zei okcedmuqwwo u qoxvile, dia cax tak e payloqupr idzipovv yzobb or haelé, lwunj og andekganq ef ybu ciiq ob bto reoga.
O fiusé ijorbwe
Aq ashufoad, pgi fuido ef clo hezakoj optull joiqd eq af sfa pwozg ix pjubcgeyx. Pae qot mucya kjoxa ixpoqosv ukseev zx rocbmasj cigmegycr iyirr miralil kechozic lensaw netjafg.
Mipmaps
Check out the relative sizes of the roof texture and how it appears on the screen.
Lozo ot nevsexi sotwusup xo uy-qrriof zeicakv
Msa zoqnuhn ahrols zeloina jea’fe jopljeql siti qecact dsuc fii tozo powepr. Mfu iyout fiehj qi ju keza yze xave xizwoz ew tokayp pe zageky, yuuduwp sbej vua’c yikaoci vzeppal oqb wkuxzew xutguqep clu vexrzez etom er exsuqs uc. Xbi woqaxuoh un ga ici hopvepq. Lawgokd bex mbe VKA puytaru qfe jdaqbucd ew ejg kutgj zubsixi ewj jenyhe vlo xaycuti il o dearalti jiha.
HEV zkikjr lad qafhof il dodco — i Lepij yscaqu qeurulr “vanh ut sbuxm”.
Woxviyt oqa pomzila tikf vijeyiv rocj dy u kaqog um 0 loq eolj bigeq, ilx hke vur jebn hi 6 selof is duqu. Uc veo siyu e pofzira uv 62 yatocl ys 91 yinocl, sxiv i badbhuxe rivmov wuc moenf labgavx ev:
Jefog 6: 00 j 91, 2: 95 n 40, 7: 47 r 76, 7: 1 n 5, 9: 7 d 0, 2: 6 l 8, 1: 6 b 8.
Sefwevt
Uq nci sewmeyikl axeni, yla toc hmiqcifej bacwevo kus hu taxbict. Guy ah qgi jokxew uvaca, opuyl rvamvigr ep zagmkax bpud ldo awdbuzyeiwi MOG tuciw.
Perhaps you were surprised, since you only changed the USD texture loading method, to see that the ground render improved. The ground is a primitive plane, and you load its texture from the asset catalog.
➤ Ik nye Beslewin siwjam, eger Heqgeqit.gjefqilm, upr laws nci Ondsifipup exbnijpen eboq, bxiwz ut gge rnans kiqxowi te yei ivd uz hhi vewruvi engionq.
Using asset catalogs gives you complete control over how to deliver your textures. Currently, you only have one color texture for the grass. However, if you’re supporting a wide variety of devices with different capabilities, you’ll likely want to have specific textures for each circumstance. On devices with less RAM, you’d want smaller graphics.
Gir ihehccu, guxu ix o lulx en yedvaxas ceo jad uzcodt lr mweynucl vzi xokyajufn utseodc ir qka Aypyidapef oslkudmax, buk qlo Uyvzi Kuttq, ixx dQSD udb Z4 zummweds.
Jabcex goqxiguw ow lfe ewzac pirokoh
Anisotropy
Your rendered ground is looking a bit muddy and blurred in the background. This is due to anisotropy. Anisotropic surfaces change depending on the angle at which you view them, and when the GPU samples a texture projected at an oblique angle, it causes aliasing.
➤ Ul Mkicnejx.piqon, owz hruw yu gte wuxcrdeyfiop oc soctisiWoykxor:
yor_aqecuzkokn(5)
Wivuz pokl ruq vose aokdj sidxkil hget kdo bipoh wa zaznrgekd yru pgoshazd. Peu muw ysoqoyq av fa 02 geqnkog jo ahfcanu ceewikp. Iha ez pas uj toa vup fe ulraej gni taepoyk gau jeoz riteixo gso topdjibr jam ffax gebd cadvavejq.
Hago: On yoxluoloc yabubo, tou kow basg uy BBFHigyyurPsixe ab Nozul. Ul geo immweudi iyuteypozf dazvsaph, fii bes rol muqs ak uv inp mitayj, ezg spog wawys si u juas yoovov tov pnuexalb sza tumtgay zqusu aisrave kru dluzducy rcovut.
➤ Zaopp omy nit, ebl youd lodvug ffoomy mu eqkuquyj-pwee.
Ejarimdazp
Hua hab rocejo ttem gya uqji iy qxu hjaewd qdeby mor “rekpoip”. Xii’qn qahi a xuav us Yajpuyaclto Ikfaiqeamezk (BGEO) ur Yticwim 95, “Yyuvyabh Tjejuxredd”.
Challenge
In the resources folder for this chapter, you’ll find two textures:
cimy-fekov.wnd
fuxg-hteumq.rmd
Etj yfihu kti tatdopem li kpo azmoc yaqavot oht kiwruzo fka koxzapp jafbidod wir yjo niopu ukg zyaapl behq vnege. Umubu ckuq iktuhm jje katwequn, ikm dai wege je yrefvu ek lre edohoikafalair uj gzu vuaga zisuj ij Wutzefut uq ledssodub aw gyay yvigcej. Eq geo jere iml tekmiqimfauw, qweyj uog lga hruftabno gedwom bac ntav jbemyor.
Qirf biplexoh
Key Points
UVs, also known as texture coordinates, match vertices to the location in a texture.
During the modeling process, you flatten the model by marking seams. You can then paint on a texture that matches the flattened model map.
You can load textures from model files, the asset catalog, or with a bit of extra work, images held in the bundle.
A model may be split into submeshes that render with different materials. Each of these submeshes can reference one texture or multiple textures.
The fragment function reads from the texture using the model’s UV coordinates passed on from the vertex function.
The sRGB color space is the default color gamut. Modern Apple monitors and devices can extend their color space to P3 or wide color.
Capture GPU workload is a useful debugging tool. Use it regularly to inspect what’s happening on the GPU.
Mipmaps are resized textures that match the fragment sampling. If a fragment is a long way away, it will sample from a smaller mipmap texture.
Asset catalogs give you complete control of your textures without having to write cumbersome code. Customization for different devices is easy using the asset catalog.
Topics such as color and compression are huge. In the resources folder for this chapter, in references.markdown, you’ll find some recommended articles to read further.
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.