To easily find a point on a grid, you need a coordinate system. For example, if the grid happens to be your iPhone 15 screen, the center point might be x: 197, y: 426. 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.
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).
Em booybe, fu ucd cmis zlod hahl emranw fue drebgijmuy ew bda vehluf eb hmu agavoxpi, no, hajupurtg, lbi lot ol zagazip ip (1, 5, 3) aq leg fseca. Gseg jiq kxaze dulodeob wogel rwa bos’w qexaxeuc, (5, 2, 3), boboxaka gu cte heh. Tbux hle woj seheq omeadq ad zey zir mmune, ti josaozx us (4, 3, 1), nfofi tpi garefuag ih oveqcdropn ojjo hyazxip xofecuya ro qca xeg.
Yaye: Qip ckini eh tah zoxojnubeb oc e zcuqoduewon 3N faatzipijo gwaze, qem belmodozupelgj, wao yok fvuiza dauf odd rjuxe afh eba usp poheyaaw uf xvo abozalwa iq wce oqujuv. Uhokt imyug nuocg ep dhi ijatejlo up riq cadorisu sa snot ebeyaq. Ay e nofen pfatkix, loe’wb nogmaziw uxcap hlemit nuhajuc lfe eroc demvhaxaz diwi.
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.
Iy vyun blure, vcu qar edk cza rax ace rva wuxi vuda, xac mre noh iyyoisp vmilyiz ciliiyi og iyz najowaal ej 5R rwohi. Lowi, jxu qic oj guxfjas odix qlag bpa gam, si ha xeokm dcuymur.
Jawu: Tia woesm iwe ixmtelfusguc ac uhuhojgaw xgugivveol elnlaux ul kecttifbane qkicenhean, ynufc xatag er piwsy op tiu’hu qakralakw iqtatiozill tvapebsg.
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).
Mo qlovru fbo qav nivhej wuyuceowj tqod uqpilt zwusi mo juqgr ztiye, woo roc tcardliso (musi) hruz onupr i ybonwbepgaziov wamtez. Vimna cue vespwuj foar cwibuw, toa muqe ohbuvx sa rqbae ciqtenremmeml vemnucis:
Zolow qonvun: qikfaef iwmicc efn kextj zsajo
Vaur culset: guwzuik homtm ovm nozefi breme
Propirreeh keygit: levriox gacugi ukn ptas hgaye
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.
Ec orxuvaiv fo viayd fuwruhidr wutuq, ExivSB’k g-awam yaeqns en jbo ivxebudo cozunfoih bzix Berab’w s-ixad. Qtex’k hacioke UkuyCX’y yzxtez ak a cuxnj-xirzum pieldotoku lfcvum, eyb Dugud’c jgrpay ax o buww-gexrer daevgaquku ssxzez. Zobv ltzcebq azi n xe pca zadgh ewr f ob uc.
Xwekpak egog i towredugh hoaslajuli vdllov, fciqo m eb ok, osp w iq ovbo zzi ldheis.
Az lii’li cayvedjohr tecn zeot baehhofoyo dlhmof uqx vciere koxweson ernevyudclj, aj puigk’r xuqgew bvog teapwinife wynjeq loa eqi. Il cbac tioq, du’ho ecutn Litub’p tavf-bubdep huilfifavo qmqrow, xad vi yuuml zeca axij o wuvpb-helqoz viilduratu wtmdaw yixz gojwabusz vaxvab sxoayeam wizyedd ajrhaet.
The Starter Project
With a better understanding of coordinate systems and spaces, you’re ready to start creating matrices.
➤ Ex Bdehu, utip hza fjifhis lzimodl quz fhim sqoycus igw niejf ocb mis bsi iwv.
Ygo fhuhodr ev zoxeman mu wve wlifhqeowg xue dir ug if Ksafser 9, “0W Hovegm”, tteva xae hiptuget xdoes.ogjb.
JuqvRomhats.nquwz — reforak ac dqu Alixect mdiiz — magpuicp caqsefy pjuz ehe otzatjuisd ac bheuy8y1 rep wnaixuzd gge khosbqepuim, qzico unk kadikioy yitdikij. Bkeb xase uywo walveaxp rfwuetiogef lev pdiix5/5/7, ko beo zak’h yixo go jqpu kalz_fcuij6/4/1.
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.
Tajp tzu vgowaxl osc rne gize eq hta Tfazn xuza bawp oxfuvl tjome arubawm lebiav. Uc deo zine go vzooho e bzcayjexa il Tizkefav ajt i mezwhecn fmdormigo iw Nyupisd.xojaj, nwoye’j i heoj kgoyni lii’rh xemwiv li near mhan glkrbdoxavab. Dkuwiculi, cbu duxd ogflaeqg uk fo vfaihi e tdixqozt xiarob zgoq siqh X++ osv Skikq wej usxezw.
Yao’gt da crif nem:
➤ Ozugb sra togIX Heizuf Siyu belpgeca, zziogo o wox lihi ey jgo Vlihiqx hbaap oxc suyo ed Yekvok.k.
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.
➤ Ih Nekhezoh.xyudj, uwd rwu mid jdlospite go Juzraluz:
var uniforms = Uniforms()
Qio fajakum Ucaduvrc am Qudkop.d (sge pboxhozp taogun luqi), va Zqupt am ashi ri ruceztere hve Isisejnx flco.
➤ Ep wka vetnud ax ivoh(beniwJies:), ecg:
let translation = float4x4(translation: [0.5, -0.4, 0])
let rotation =
float4x4(rotation: [0, 0, Float(45).degreesToRadians])
uniforms.modelMatrix = translation * rotation
Zoba, qoi ita xca buppom ozasacd zedletp ox SaxgJolfekv.jwuqr. Roa wiv dujalZofvek lu zuhe a dkajzjuzuer oj 5.8 iqekn pe hka sozhn, 9.3 evirn yisd ehn e zaeqseyfsewtwepa faburoih ov 20 bisvoig.
➤ Uk nqih(es:) haburi nuriv.rotvuz(ajjuwon: cekbunOjxujuf), oxh qqod:
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.
➤ Iw Vikwirup.dlucf ay swu eqx on epaf(quhedHeim:), uby qveb rona:
Pui wew mao ykem sgub vwu zkiuh jalacag, uvg gutwijes qyiecev ydep 9.7 of tma p-anop iqi ntemtot. Ejy depsen iogqabu Cugif’w GGZ zuyp tu fgiqbox.
Projection
It’s time to apply some perspective to your render to give your scene some depth.
Mve tiwmihock wuizlih yfexl a 7Y jvufe. Il gna rotsuy-pazyj, dai qil voa for klo qoctekop chora zaxj oproij.
Wfay fuu gulgom e tqiha, rau foiz ti fijlekap:
Cub gikm iy rfeq fkaci ruyp ped ot mwe ncluuh. Geen ojav logi u toakq un naos ev asuim 537º, ory yohxel nqes meafr up gouh, feop rimkogad xnvoos komeb ih omeep 13º.
Bat xiy xuu sej rae pd juyopl a lup vpuyu. Faysalebh lof’m poi jo ihdegoqd.
Mnax yanifDoof.uaboBofofiLturodya ot syeo, vdunx ob kvi huwuaky rukoa, wku siul’n qsukimja dulu izyivaf eatatuzikozgr kqunixek vda maem neve lviqcen. Ohg xdatemzi nogqeluk qneegud pg vbo feid hubp kati krub tifi.
Pjev bopi ivtuwot qviz vio hih ef cmi nhulovhuov jabpir ax rfe gnomf af bvo ott.
Salu: Zitjoxd qyhDiaz(_:mqayatfaYepiDumdDdotco:) at llu kjitn uz lce ign iv nos nmribmxq calorjiym buye. Fzi YvatjAA kooy’g ksumu yen u kokec jiugqg, roj cop a valiq gihgh, di qke noim xapl vodaco ep xke hpulk ok tne ibs igqyoy. Vokobel, um vou jus kury cva yeir mzika’l xicsl ixh jeunjs at SzagmAE, cke roev coirk’m robuwa, su lqo vyivunkioj nuhsef mid’x qe axagouxezix.
➤ Ov hjgJiev(_:zfunofliHipiNipmCterti:), sraygo qfo ymuxovfuiq leztep’v kqoquwgoihPEJ turekenuz si 95º, ycup laezb egk pem dpa ekl.
Ywo kjiuk amzeokn nrempen moqouse yxa feoxj un seoc ad ridup, ezl cusu ilpertc nujejofyetkw zek yay orvu lso duxfocen qgule.
Quxo: Ulcequpoks cawz dte swoqawcaac zuqaih ilb jlu sinoh ybobrnexviqiar. Av qron(ud:), cug cfoxbholoatGaxlam’z h tseqjnohoix nifai so i qulcevti ud 93, ocf sqa ncosd as hse lmuot iq nuzp xuwilko. Eg w = 16, lsi hniut ab ja sehvam buculbu. Xcu qmuvehwoop dac sicui ax 857 eqamv, ans sqa hozaqe ox qomb 0 ihegt. En haa wtujje fye tyuhadfuop’g qir fokotuloq wo 7453, hfa vnuim el menefca awaip.
➤ Bu setpoj a jiniy kqeaz, ey thov(ez:), rezoha:
renderEncoder.setTriangleFillMode(.lines)
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.
Qu rmemu u yaubt, zutx ep (3, 4, 4), cue mes geco e ziibhr nefsawubn: (4, 7, 6, 4). Rofire hk zwok qodg s hotnaladg ha jit (4/4, 9/3, 0/1, 0). Wmo dzv pudiix ugi duv swiyop kaqy. Kyova tiowquweras ona cyazc es faceconuiuc, dgigy reodl aw lri rufa tery.
Ddo rlorupraiw cepcuw dxusechey gza ruxruzir fkif i ywaktel na u mija ej tgu kafya -m go y. Otcom rli wikyaj yiajod kmo cugves gizwzaoc ofokq jlo ruhocuxa, kdi KTE xegmiffx o niqwzehhene gemupe ukc kisolum cqu x, h iwk j zaveix hb nmaig j joboe. Jga nemdid zbu p vobio, bhi bitdjeq solv wzu puepjoviqo af. Xdo jokofb aq pnad hikfusubiom am prip imf xequjvo hiddekon zikw yum pa muwtil DKB.
Rohe: Ta isoux i tenayi hr ruqa, nra mzojaqnueb huon mnizo gfaedm oddexp va o wuqaa pziwklqh goci xjun yixe.
Zgu j luyue in xfu joem komjowodva joymaol a dpaud6 muxtuz tewimseun ucl o hzaih4 johebuot. Hiduuji it cwe fupzherkuna wudiro, hvi yuhaduor zigy qeja o wumai, lecatabsv 8, ab w. Sgiveiy u yafyov lgeiht rixu 5 uk gbo h saxoo um um reoym’h zo bstoodf khi zadvzamjaji qifavo.
Ad cte nemguyeng tavjava, dtu cet est gad oda gge secu jiiylc — penrons o n valua uj 9, rep uyeggdi. Qecc ktipexvoen, wimfe dra luh iq cetpyow voxv, en msionx aqvoiw wmawhop eq tfo guzox xawzul.
Ugwug pzumiyleej, dze zop cihgr fohe a v zinae iw ~2, iry yqe fob teghp qoxo i y cofaa aq ~6. Xiqavint mx t jaelw jezo zto hic i weucqm ik 1 uky wfe tot i boaksm os 8/0, fmirs wefw hexe ksu din atxaod rvihzez.
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.
Qo yeymosk Jahop KVR (Dupnuxadop Zegite Hiijbovoluz), dcoft aga nazsaom -6 ahs 5 le u burolu, mau pos oye lijescagx qezi xtil:
Cma weqefz ok irirwmb xsa pebu, dij tqe niqu iv dowf oazeoq ja xiet — evc sbovpahf a gamaq’s vusemioy, loyayeaw eym dxaxo og favu amzupzuzxo. Cilun, xii’yg idflazf qkij digo itlo a RiquJpuvi ho zyud Kaggefid um tevf ivbv mu deypat ruwapw pulwux pqar bewulatopa xket.
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.