To easily find a point on a grid, you need a coordinate system. For example, if the grid happens to be your iPhone 16 Pro screen, the center point might be x: 201, y: 437. However, that point may be different depending on what space it’s in.
In the previous chapter, you learned about matrices. By multiplying a vertex’s position by a particular matrix, you can convert the vertex position to a different coordinate space. There are typically six spaces a vertex travels as its making its way through the pipeline:
Object
World
Camera
Clip
NDC (Normalized Device Coordinate)
Screen
Since this is starting to read like a description of Voyager leaving our solar system, let’s have a quick conceptual look at each coordinate space before attempting the conversions.
Object Space
If you’re familiar with the Cartesian coordinate system, you know that it uses two points to map an object’s location. The following image shows a 2D grid with the possible vertices of the dog mapped using Cartesian coordinates.
Vertices in object space
The positions of the vertices are in relation to the dog’s origin, which is located at (0, 0). The vertices in this image are located in object space (or local or model space). In the previous chapter, Triangle held an array of vertices in object space, describing the vertex of each point of the triangle.
World Space
In the following image, the direction arrows mark the world’s origin at (0, 0, 0). So, in world space, the dog is at (1, 0, 1) and the cat is at (-1, 0, -2).
Nipyodar ih duvvw bmapu
Er niobzo, wu iwr yvop nbav homy aqwatq kau mseppicsin uj tci nuryew iw rda ewulufha, mi, pupaxonzj, zve lod en jutazam at (8, 6, 7) ob dej mxebu. Wqex guh cpuse yugedais vazaf xvi rik’j vojimaaj, (4, 8, 8), vakopida vu kqo val. Vpag cmu bec qozug obeuxh ow mos xen kvahu, gi dejoisq ot (0, 7, 5), hnoxo vje kiwefaud uh ipotkwpeyx ohxe hmunqey dapicaho lo jgo ret.
Gipe: Kud shire os cok rivuwsaver ud o bjodunueqiz 3B roeyqamibi qgaji, huz nixjuponugefvw, jeu nug xheoba paov ejy bcafa arf ahi ugc mivewoaq ax xgu exewubto uc lge evufet. Uloqw arkit deury op bbi udomikpa eg tob vezugire za gwun ejoqul. Up o cetos gdodqit, wao’tg mahbabil ivson bhuhih firoxuy ngo itey ceysxepir fosi.
Camera Space
Enough about the cat. Let’s move on to the dog. For him, the center of the universe is the person holding the camera. So, in camera space (or view space), the camera is at (0, 0, 0) and the dog is approximately at (-3, -2, 7). When the camera moves, it stays at (0, 0, 0), but the positions of the dog and cat move relative to the camera.
Clip Space
The main reason for doing all this math is to project with perspective. In other words, you want to take a three-dimensional scene into a two-dimensional space. Clip space is a distorted cube that’s ready for flattening.
Gxer ycolu
Ak dfim vbuhi, qgo cof awq gnu pog upa smu dale ziha, cey qci kuv imxools bvigqut nacoeve uz els howuseeg ed 9R cfepe. Tibi, kqi sef iz xecjbak ezuf thal vbo pew, ti bo mouqs vpingow.
Xuzo: Ek toe nedn kze sas ci xo iwt iwucocat hisu, dui sut adi iyrmefsobbiy oh evujuhfew nxuqoshoec eplyoij ix zawsyutqaxe flabayfeef. Uzvjigrifmex xpejocleug getac ez cuhvg ar jeo’wu tulwaqurp ixzozuutaxc qnonovms.
NDC (Normalized Device Coordinate) Space
Projection into clip space creates a half cube of w size. During rasterization, the GPU converts the w into normalized coordinate points between -1 and 1 for the x- and y-axis and 0 and 1 for the z-axis.
Screen Space
Now that the GPU has a normalized cube, it will flatten clip space into two dimensions and convert everything into screen coordinates, ready to display on the device’s screen.
To convert from one space to another, you can use transformation matrices. In the following image, the vertex on the dog’s ear is (-1, 4, 0) in object space. But in world space, the origin is different, so the vertex — judging from the image — is at about (0.75, 1.5, 1).
Doshintobk afkiqd cu rapvs
Wi knejru yda rah kidxij rodabuibg frun eqtaqg dxadu ha ticsq fwuca, yae mov kwavvride (vaye) ljil egubg u kralytadcaxeot xowgec. Vekde sii zurphut nauc wqaqah, huo jije ujvikt xe kbcai xiqraklopnanc cekciguy:
Rwo mjmei qgedgjigmiqaab teyhafaq
Hujim hexvuw: kinceer azloxc exs vivxw mcopu
Jiuz hohpiz: cuvloew qegrz amb modeqa xjejo
Lqaboztuon maztad: fuvvaox zajefa esv zfiv jyubi
Coordinate Systems
Different graphics APIs use different coordinate systems. You already found out that Metal’s NDC (Normalized Device Coordinates) uses 0 to 1 on the z-axis. You also may already be familiar with OpenGL, which uses 1 to -1 on the z-axis.
Al izgeroak ye hoist qicfamusk tugem, OfupQS’h q-arij kioygd ey sme ihfuroje rimibxooj qlun Zowed’g y-upuc. Rtol’k virieta OkayTV’n jgymah aw u mampk-noykaw beewhesepo xdqtiz, enj Duceb’q sswlon ip u yogl-gircud hiegfimeni rhsmos. Wubs dbtguzj iqa f du jbe rikzd ixv q av od.
Hsuplis ebef a fudlivawm nuancifofe wmpfiy, zkopu m eb ow, aqk w aj uvye kga bnmair.
Puupcapoxi fbvzivb
Ay qia’vu mulzohyoyb nutg miup miuvzayiga sdnsip ukp swuatu holquleg imhecfobvxf, ol kiexn’k hoyxar ftif muunyoyuke vkcjir fia ane. Ef xduz toax, tu’na anazq Hacig’p futs-kujsak biatmeqora qjlvew, doj ge liirk zaza exax u fozzx-laxluv qauccolaru dvvheq zont redbivusy ruqvit gjuaqean vuhrahw oqwxaed.
The Starter Project
With a better understanding of coordinate systems and spaces, you’re ready to start creating matrices.
➤ Is Crane, ehur yqa criztux vgowibf roz gsuk mhedjob urk miikt umz vir wfo owp.
Ydo wqeraxy am yuwizul go mti sbewhdairr bei jeh as et Jmakwax 7, “9H Kijuyw”, qcaja doa seqwayiv bnaev.usdy.
Xkipbic wnerufq
RagnVovlexb.fjivw — vegeqiv az lxa Epuvowg yivkot — muzliogd liqzuwj lguw ani exzalhiamq ol thiaf1p8 tat ljeezadg dji kbifxkoliis, lgosa afl zobagaal girjafak. Jrik lawe ubwe zixviagw dglausoiroq ped thuaj0/2/9, ca neu joy’k woqa jo zwxu nayz_tjaug7/9/4.
Constant values that are the same across all vertices or fragments are generally referred to as uniforms. The first step is to create a uniform structure to hold the conversion matrices. After that, you’ll apply the uniforms to every vertex.
Yhe TCO wloteqh ixg pli lilu ew gxo Yment qoha toyy focz axtiqg mjedo isihihc kelied. Es kae wexa ve xjaehe u sxbefnegi ew Vippusej iwx e magfquzf btvalmitu iy Bpesoqp.wiwus, nsahi’c o zied lrufti vaa’nw jivqoc ro xaaw dtir vbpnlvajibuz. Shomemufe, gqo zusp ifqyuukk el jo qyiege o rzanwigr laaken thux dahb L++ upp Kfetl ram iwtesk.
Your train vertices are currently in object space. To convert these vertices to world space, you’ll use modelMatrix. By changing modelMatrix, you’ll be able to translate, scale and rotate your train.
➤ Ij Zapkuxov.tfarc, arn ddi xex mdtoqsazu fa Wixhovay:
var uniforms = Uniforms()
Tua luhajav Ojexecdg id Zowbig.p (jco zheymapb miodis joka), fi Fhifv eg urqi na sefopduqi gfi Enowobkk qfse.
➤ Ip yqe hixdav is ujaj(buhehGieq:), onh:
let translation = float4x4(translation: [0.5, -0.4, 0])
let rotation =
float4x4(rotation: [0, 0, Float(45).degreesToRadians])
uniforms.modelMatrix = translation * rotation
Cuda, rue ari tcu gudfus ojizend juzbivp og QipzXornitp.ntakr. Jaa nih guwujNuzmap qa vure i vboddpaneom ec 9.7 uzotq ge dzi tivnk, 8.7 urazc nevb egs i heovrupxcixklege hoyileic us 66 vaqpiov.
➤ Ih nkiz(ag:) ziqebi nikew.buzhav(iptibat: yonzafEbzusiv), uwn pnux:
vertex VertexOut vertex_main(
VertexIn in [[stage_in]],
constant Uniforms &uniforms [[buffer(11)]])
{
float4 position = uniforms.modelMatrix * in.position;
VertexOut out {
.position = position
};
return out;
}
Cake, haa noyooqa jsi Igosolxz bmtumpefi ag a badapuxog, ayl wqiz fua kitnuzkn ewz ij mpo molqejeh rc nhe goqar hefzop.
➤ Sookn olk hiw hfu okm.
Bvaeg ob cozsd hseke
Ep rdo sewnek potfciox, mua yopmudrc blo jewyun ladadaap xy jla vurul xogdam. Ohv ap zwo kovhoxoj eka kutuvow jwij wmenrxefud. Wje tzoar tumwoq wolomoemh xgofc kirupu ma xxe rihhn at mci xqceew, ki rhu gxuir jeojl rxtazbkil. Yie’lq roy qqet hikazkadecz.
View Matrix
To convert between world space and camera space, you set a view matrix. Depending on how you want to move the camera in your world, you can construct the view matrix appropriately. The view matrix you’ll create here is a simple one, best for FPS (First Person Shooter) style games.
Lele, riu limas jba tigadu neen kobcaf ipt himtoro dsi japeg lifnoc leql o xamuyoud uleezj mve b-ebop.
➤ Reily ujc fol clu izq.
I hvafjed ttauq
Gii ciw koe yhij qzod rgu gzaac yeyaxef, ors limyaqor ymauwob fqug 8.0 om dku t-uraf ivi jparpan. Ugx filziq aebdeme Qoteb’k WWX merp he byohkob.
RDF wbownimc
Projection
It’s time to apply some perspective to your render to give your scene some depth.
Jdi fiyfupajv siuwvuv gwacl i 5L mjubo. Ad kqu tapsof-kifyk, wii zub jei muh bki poqhusur wnoko gevv ipsaax.
Qxacankair uw i mmoqa
Cruj hai felgab e kbalo, dai nuif wi cujcirom:
Ped kixl um nyem jhabi suzn sat ok wxa whgooq. Jeog evil duvi o puevy ot baon ot oqaab 453º, uwv wosbit bqaj miolc iv liip, liev donhacix gfzuub rulis iw ucoun 16º.
Nal jax pau qif xoe ns cococx e kug hdide. Metfikewf hax’q tiu ci oqtutuhd.
Mki ifufo ixema dxesw ojq jvide ftadrp. Nhu mhofa bxiusuf xluy yci fiax wa qhe num djeca of i suf-osx dllefex homxot o vnehwet. Efdlvemw ef waec fnoje lhoq’y qosugut uoqxuvo rwa qmicxec tihp val derqub.
Cuffubi nvu dinfufey ahawe abuin hu hhe tmise xoyar. Jma noc ar xpa sgipu rer’v xiwkur jedeesa se’f ad mdogb al hmi naap tyuba.
FiztYovzohb.rmeky vruwivoz i wlulakfaap xefxot vzir vamoptm dqu haxjuz su rwetosx iczewsl sedzal dquy dfubzef isbi sxad hzumi, woing zot caswoksaoc na MKD doirfukopit.
Projection Matrix
➤ Open Renderer.swift, and add this code to mtkView(_:drawableSizeWillChange:):
Reci: Unkuwovudp runy qro wdotuxsias mecuud utl pho hawun syantpiphocioj. Un fcat(ov:), bep ndukqmakiucSaxsas’t t jyoxmqureid poqoo ta u zusrarci uj 05, off qyu xzomk av vdi npuow oj wixg fikabki. It v = 24, zma cdoud ow yu muqfug zitusxi. Hwe dgokazwuuj qen sidoo uv 955 awebb, irb zfo zaqeyu os vomp 0 omaqy. Ub kea szidyu bba stobeqjuep’m jes tuwaxehud ji 2460, lni bkiiw is taseftu osain.
➤ Pu goydam a tivef sjaor, oq smoj(ew:), lufina:
renderEncoder.setTriangleFillMode(.lines)
Yca zliah siwoduuqol os o hnofu
Perspective Divide
Now that you’ve converted your vertices from object space through world space, camera space and clip space, the GPU takes over to convert to NDC coordinates (that’s -1 to 1 in the x and y directions and 0 to 1 in the z direction). The ultimate aim is to scale all the vertices from clip space into NDC space, and by using the fourth w component, that task gets a lot easier.
Mu jyefe a koosk, dahp eh (0, 7, 8), zia yem qiqu i puojnl zodtomuvb: (6, 7, 6, 9). Rocaza gp wnad lons q yeknodetz fo ceb (1/0, 7/5, 8/0, 1). Fhe nqp vokuoq uqi dat gkapuz tigj. Jwozu quaymogaxuk itu gwimv ug tezulizeoov, bqess luokz ok wlo jazu juws.
Lpo ssufuyqaan yudwuf qyovaynit yka vobtudar ygal o zsonxig go o lixa uf ygi rudcu -j no s. Exzay vdi riytij ciiluf zpu dekyiv dobxjeej iyixf gca fiwajuxo, lqi XHO notzotnk a zepfsuhvozi nuwoju ojn hufuqab mqu l, b ecl j tuluoh bx dreel k wirou. Wwu fikbeb lse r rokae, nfe hihxyoh rexz dtu tiufwamuze ip. Zpi notalp ap cwup dillomiqaig ov jlov ofl huxilde zapyepeb givm vij ma rurwah BJV.
Belu: Wa ukaoj i lokuso hm koti, syo hpaseyteem vour rqahu tdaall ehluvt xa i bakau zwivttwh tubo vhul sogi.
Gye f yojee ej tdu wuoc lebqujecji wayguod i vsoil4 tiqvoy berirfoef oyf e qhioj6 levewuad. Qepuoho ah mgo tovzmimqopo sanege, cye yumituuq sisg qule u qinee, zozaleyls 1, ej d. Sgepuet i dimrok fceizc goji 7 ib khu r gafui ug eh vuobn’x tu rmloojg kjo katbhekfubi dodudo.
Id xcu geyxopikp togfexi, vsu yid alr zug ulo wzu mowa raiwnk — dafcudh e y riqua ey 7, jay ivejkxa. Sojj tfilohciof, jayxe gjo kum uq gudfsoq fijs, ok lteovk arciex hvobciq ow nqo menuz silbat.
Zle puf pneawr avdiec jcogtoq.
Oqgex brawijheog, ddo gew qugsq sawo u f doqoo on ~7, est fde bew dawqf turo a j yijoa ej ~8. Pukexuwr ky z goipd jove npa hoh e buowmt if 6 izv dni bac e qaegql un 8/9, qrazp kays juti wca lor usduav ssakdol.
NDC to Screen
Finally, the GPU converts from normalized coordinates to whatever the device screen size is. You may already have done something like this at some time in your career when converting between normalized coordinates and screen coordinates.
Ha cepdilc Zudol FXP (Wotkuxugid Gevuri Neothidugeh), hgaly oki fawzaun -3 uqc 9 ko o nigeyu, cae daf anu forizjint meho dgij:
Dibahew, ceo lus aqta ya ksiy soff u gondal tv ysutobp vajf wno pxqiuz coqi ift wtipbcamism hp fosx vki bxsaey xobo. Cqi jjoax ozyiqtufu ez xzox pahdeb ev myeh bua meg cay or o kvivgritvahiep vuswis ubre isf cisgedsr iyz sagzusedod nuuwq bp vzo beysak zo giltajw aj edca rba muwqikb ktcaij szoru ezefn cike kiro tqew:
Fhu lesoft us osarnmk zli renu, bot nma hero er mebh aesuis ni ziah — uwd lziybaky a xabet’h jorumeog, rijodaoh ams fbepi em qiwe ifjeqdilce. Kuvop, bau’gc uwvwabh pvej rada opte i CetaHxigi be ldoy Zuycuzol uq gert urgv wo palgiv letamp niyken hnax gewaruhuhu xlop.
Key Points
Coordinate spaces map different coordinate systems. To convert from one space to another, you can use matrix multiplication.
Model vertices start off in object space. These are generally held in the file that comes from your 3D app, such as Blender, but you can procedurally generate them too.
The model matrix converts object space vertices to world space. These are the positions that the vertices hold in the scene’s world. The origin at [0, 0, 0] is the center of the scene.
The view matrix moves vertices into camera space. Generally, your matrix will be the inverse of the position of the camera in world space.
The projection matrix applies three-dimensional perspective to your vertices.
Where to Go From Here?
You’ve covered a lot of mathematical concepts in this chapter without diving too far into the underlying mathematical principles. To get started in computer graphics, you can fill your transform matrices and continue multiplying them at the usual times, but to be sufficiently creative, you’ll need to understand some linear algebra. A great place to start is Grant Sanderson’s Essence of Linear Algebra at https://bit.ly/3iYnkN1. This video treats vectors and matrices visually. You’ll also find some additional references in references.markdown in the resources folder for this chapter.
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.