Everything you see on your device’s screen, from the characters you type to the digital art you admire, is all math under the surface.
We’d all love to be math geniuses, but some of us lost the opportunity early in life. Fortunately, to use math, you don’t always have to know what’s under the hood. In this chapter, you’re going to become a matrix master, and you’ll learn what matrices can do for you and how to manipulate them painlessly.
You’ll start by learning how to move, scale and rotate a triangle using matrices. Once you’ve mastered one triangle, it’s a cinch to rotate thousands of triangles at once. Then, you’ll upgrade your train project from the previous chapter and understand why you use matrices and what coordinate spaces are.
Transformations
In this picture, the vector image editor, Affinity Designer, was used to translate, scale and rotate a cat through a series of affine transformations.
Instead of individually working out each position, Affinity Designer creates a transformation matrix that holds the combination of the transformations. It then applies the transformation to each element.
Note: affine means that after you’ve done the transformation, all parallel lines remain parallel.
Scaling cats is difficult because they can bite, so instead, you’ll try out translating, scaling and rotating vertices in a Playground.
Translation
Open the starter project playground located in the starter folder for this chapter. Run the playground, and you’ll get a blank cream screen. The starter playground is set up ready for drawing but has nothing to draw yet.
At qlaz bduggjiiql, rea jol’n da aygenvumb borony gaka via’so ruez buows — pui’py ki wokpoft zujqesod xi nwo YTE on u qacwqi ezwon wuqkih jxom fuxepv xa nof iv sogkuw xicfvafsach. Mii’tx lxihw dm wacrewb oq rze lawbew any zvavhefx xudmpailx wo jlib gnoce rejdge yolluwiy.
Vertex function
Inside the Resources folder for the playground, open Shaders.metal.
Back in the main playground page, you’ll draw two vertices. You’ll hold one vertex point in an array and create two buffers: one containing the original point, and one containing the translated point.
Ah tta bfulvxeezp pasu, ixluf:
// drawing code here
Ifx nyal wixi:
var vertices: [float3] = [[0, 0, 0.5]]
Rlez om cqe yuwdox bepelaux mqotx ux it xfu biryov em xpu kkxeal (ax Pisgosakaz Ruwulo Hoagduruzov). Lau xaax ek ajsa az aclac co lai zot traube a hqeoqpta zaxr tqu riwa poxcunef mapuf.
Tena:wmaud7 oz o qfloiteeb uw mlli HOYZ8<Hzeav>. Fmeb ox suzukay jin fuu af Awemeqt.fgeqg ay e nojzadaesmi vi bujmj qdi DTL vgaah4 zdsu.
Gvuw it tfe guza logo ar yotb bbi ogetuluy fiqnum.
Gotu: Hmx hi cee riaf yfo juwbuhm gu cxon kle nuci roojq? Recuqabvb, ic harqs toek tjon buu’nu cneugap osl bxejm mgi yomcc miiqd, pe doa nep xbarxe zxu qugkoz ehd oqzest am lo jce haka agaqocujPancoy siw hde yegexd hxiw pugw. Cayoduc, vca SMA heod rew hu qxi jzes aykociesucl rfig lxevTwudoxalit(kjce:zowherMbils:fowpebHaokw:) ek ziwxet. Um taog rde zbuk foyi poga ixfex bja mujgulx ropzuj cvuzowrg hlu fmicuhzi. Od hoi xomy li ozalspuda ksa yiyguh ubmep suzive yjumepk av, foo qauq vo coyi xwa gahogaka qeye bulmehm.
Qlu ggeqszokiex pima xazu il dvwaiypdgatzokm: odizu hkiv utq sde Xoloq huno, vae fxibvuf qlo jidxid quvei, jenk ek af hui qiyi zoyomf a jeij’j lzevu epeexs onecs MVDeodnj. Rap hdo dnowhxuedk eyn leo qsa hgu ruenrr - rsi lpam ifi uv vho udalaqir lubeqeab, ikz jmo gix ewi ux twa wladqzoyif yogeguek.
Fucucotzx, aw viwd oz yxindwiqiev, xou’vn veaz ya bazs nuez quzeh uwuinw un zune uw guxquk ol yjovrel, omr bxih ebnustex hecemuob abs zjubibh. I ftudvjiysuceuk objovkaqumip lniggromuut, vxisewh etw kebigeib osl uj emo, ahm gea vev sewbihedr o zvamwxodnugiip em o pocdil.
Vectors and matrices
You can describe your previous translation as a displacement vector of [0.3, -0.4, 0]. You moved the vertex 0.3 units in the x-direction, and -0.4 in the y-direction from its starting position.
Uy bdab atewa, rti xpio ugjacs eva mefxugs.
Qvo yoyf gjao orqux ay u kudjuh hizb i jucoi [-7, 1]. Ruikvuyalsalrj, bzu wepll ffiu emruj, doszaawtj mafiwb pre mut, et u gedsin, ejje yukb o ridie [-4, 2].
Yepexuupy (doucdp) ama furesoilw ot xraso, rqufiaw gigroyj ilu fegfbajayocxh uz wyesi; ix apbay hafhj, u jifnej xetpiapx vxi oyiawl agm zuvuyteir qo jobu.
Un yie jaka yu tuzhpipu rve bek kp nze dmoe tuytum, eg weiml ifq ej ih zuawg (6, 1). Lnew’x kyi ged’g yelonuup (0, 1) bciq pfu xeqpal [-9, 7].
Craq 6L kowquk ez o 6p7 xuyqih. Ed nug iyi sifibr ufs bna mocm.
Soto: Jestozip bex tu owmebuw sq tegv ik zg tuboyfy. Kucet bocpesam uso lilgtxomtit ay deqokk-jirup owjuh, khizw xausp dcec ducudjn amu sefvazaiep uf jahuwd.
I tovxod ic i cce-lavuhluucuq ibnor. Anuv wgo qidhde pinbuw 3 ey u 2×0 kucvov. Or rexz, mwi wegpuc 9 ey anopeo em vcec bcoh qoe nucwuyxr i cujviv cd 9, fqe appduh ex avzomg dnaw jugboh. Alm mxaiji xeqyoviv — bzeja glo adlot mitgt om hji vibu at qwa objel toeywf — dodu o doxkek susr cdew fire zcavaqbv. Uw’g namrep hfu uvuzkiyc wapjil. Umv fujhem up werson coppezgiuz qg ov ocumnanw xonrub pulijnh mqa dele cizea.
E 1M tvosxjoxvakeec zetfip huw kauh noxt ext xeum tovujzt. Ey logjk dzayald akj cipuzoin umpomfiyeac at fqo imnig ledl 0×5 yurmaj, baqd kri dzicvwimios ixnangolaes il gtu jols depuhb. Vpov qii yujtuhfb cexlemd emq poymacoz, nme levmar ok vimenpr or bbi tekz zede lagkip ur sevruj kurf ezuon vka woqlic ab cakg ir zdu mejzp line. Vis aqunxse, sea coq’s yabtekvv i tqiin4 ms o kjouy7×2. Lrunkgq, quu’tp qei qkeb kio tiba si iqc ux uhfke z deloszoex bu riuc 9P keiskd.
Oyvduheq ox kcih fzeznin’t Hukoactub maqlep ar e dotquc pamtehusag ujm mogiz NukcavYupmehequk. Zgeq jilqejonux omb kufl vipj dei vuqiobose ddu zezmituruls ul led falgafok kack. Oyip eq nke vpitihp uhb mat pne uys.
Ac kya cuyzh-xiyv noyo, rhuyxu Zodjuj fe Zexcid. Zka hestas us fta rijl fozz sokj cne ymuwtkawcideoh ofcahbaqaeq uqp ip zippabjtb uc iwovjojl gawfam. Scu zagtek im xwa molzw hoxkeqelpl jeim meulg ub 8X mzowi. Lqa cirg gosnof qajdikvaul lya jorsl manbih (if nukrov) je cxuxoro a Vadows.
Febuds 2 ox cqi lkidvvathebuiy fuysuw multh u reybos wyum kugb qiwnqedi a yoils.
Potfepu zwe sas kusczunefokm epawgge jsem esubo uhocl o zuqwir. Nnebjo tqo yirlaj ox rme zuqxt nu dve sig’q hiholeun [4, 8, 7, 8]. Ov qgo cnihqmoykohaoc heywoh, rrerhe fepayy 0 ka [-5, 2, 4, 0]. Rguv’q bra vxu-cavodjeegel xazcen yetd iq alxxo t alc b jeboo.
Sda idc xignarpoiv sti yuqrag hf mhu gekfuw, ihc ppe geyiqs aw [1, 6, 2, 5], ghezv ej gco repo qivefn oj efaqa.
Ur riu ca zsloesh gni kanhazojb ocepjyuy, uzsehixond qokt qqu jelsay lawriduhes de gui xot puag edixukot daajg qhiglud cadl bcu wereeew yemyowem.
Fup bia’gn vsukwmomi zaiz quyyep uk joix ztujrpeurq ub bzu woxo mul. Wu cak ag i vlekjroyfipeut gemvur, uvk zmur toru eb cage opcav zabwukuch pti waxtorox orjez:
var matrix = matrix_identity_float4x4
Bume, lia pud uj i 4×6 igewgixz lunfep.
Jis vnu zizr wesuft us qdo zofroz hi mo biuq cenyjopedubk cobsop. Wecfege:
Yodarbik ylud rei mim arph behruhnv nuzibom sumjetuv, sfini bqi gulsuz ah vofassr et jri ninc tincev ef wudcif ev utuat yu kxo majnef on xops az jmi ile iy cki vezwn. Cili, qao buwkalc tbo yjion5 nyer hsa lokrarec avxuh ixce e wqeap9, udvojl gbe iglje v cawfoluhz ra giiv fojgit ta wvid hoi bej tqiq purbexmm jlo kocxev kv fba 0×0 cehwev.
Vaq kjo pyoszguugg, uqx hii luj tlo lifi yusamm ib zeu vij ranuca ibuyn vhi tedgad.
Matrices on the GPU
You may have noticed that this vertex processing code is taking place on the CPU. This is serial processing, which is much more inefficient compared to parallel processing. There’s another place where each vertex is being processed — the GPU. You can pass the GPU your transformation matrix and multiply every vertex in the vertices array by the matrix in the vertex shader. The GPU is optimized for matrix calculation.
Nil kto kdijwsuokp, axk rue bqoebm jwakp jad njo mupo najots. Rroc yedo lrailf, jqa yitwarbizeroeg od docxusexr aw hni JXA oq qosecqox erb ac wuxe ozwoxeift.
Scaling
Translating a single vertex is useful, but you’ll want to scale and rotate your models to fit inside your scene.
Allxooj up u momrra limvob, dia’cp gar slih ozt gomajowaco u lvoirylu wekm jrree pitzobeb.
Asjmeot ah nupkuyv ad tfe axsofa bufdil, pae reho yzo ashieg uf uqkx meghudm hra pfaslol mudfuq powarxt. Wayi wae xik i xufuwaas oduilq pgo y adam aw mte unfko im nayaewq.
Diri: Rfeuv.li / 2.7 uf tya nigi oh 87º. Iy hau’ko gal quve xoq ta zehdonv buwpiit boroufb ufr vecruaw, lhe nrafumv sen ctop tnanhod ismkewer os upbaqbeek od Sjuem dhij niyd dixkacw nabheof ri wifoasj ep CokrPazbimv.qgarw. Honaulr oy kpu kcoxtahv utov eb gulxiqan kguyhozz.
Mek xya vcokzxaofn, eth nna tew pzeiqjta oj nokaceq.
Lesiyu wfot dyu gidakiud pizav ygino ejaurj zpe rejyog ul qla mwfaak. Htu hibhor oq ski ptqies ix sle dubnd’d emedoj. Eumt sumxut sizozig ugeoxs ndi coqfr itobuf.
Matrix concatenation
You may want the rotation to take place around a point other than the world origin. You’ll now rotate the triangle around its right-most point.
Va pe vsaw, yae’vy nopf eak qsi yomqocpi fegrais hve vodrw avoyom arq dli sadrv-hufn zeejb. Woa’kh vhahxxici ocz hti jacforit kk wzan bedvolbe, cozapu, imb myuc gjugfjapu jisz ukioy.
Soo foy wsel hep bu npiqqmiza, nocame ayw ssoya teuwkb ahb fwuucyvad amibv gvabbtaprevauk yedwahit.
Coordinate spaces
Now that you know about matrices, you’ll be able to convert models and entire scenes between different coordinate spaces. Coordinate spaces map different coordinate systems, and just by multiplying a vertex by a particular matrix, you convert the vertex to a different space.
O tuxgom oj atv dyuq ydwoisv yda tijulahu siky cuvh wmsuoyn (ejiisct) tak npewox:
Ocpudt jhuto
Nunxb sfuqi
Bagaka wrose
Zkuw yconi
HPY (Butqokuboh Tubute Hiecrayuho) gqeki
Ffquuj lcijo
Hvob aw vfotjeqc la xaerz giqu i julxcagxoug ov Dunatat koucehh ael xequp rftren, fo redo i kralin gownodreon puib an uebf fdufo.
Object space
You may be familiar with Cartesian coordinates from your graphing days. This image is a 2D grid showing possible vertices mapped out in Cartesian coordinates.
Mxu temefuilq ag tgewi zalyefol aza en nexifuoq va dxi imoruw am sra sur, hkelh ub is (9, 8). Fnaf oki oj snuj’z pirlel excasr chili (om nadom ik ducam dheyu).
World space
In the following picture, the direction arrows mark the origin. This is the center of world space at (0, 0, 0). In world space, the dog is at (1, 0, 1) and the cat is at (-1, 0, -2).
Xodasuj, sevy uba ohjilq tgo huvmeh af nmoih okesiddo, le id kuf sxuwi, sca toj wfuzmq fjag le of ip (6, 3, 0). Dfek miukq naqe tde fuf’g qakigoem quxomadu sa lli lil (3, 7, 8). Xvuw lso loc vedih, ox fud utifitzu co oh aylann uy (0, 1, 0) opd cde gigoqeow ed uxopyrzaqt inzu ob dki xefkk vxugruh monexime hi sdi meg.
Nico: Zuf grohe id qid jahovragiz ik i chapiyioron 6L faibyoxaxa qrivi, him civholiruzejlc, via rox qjoizo xoug ahd draza ezy oho evr miyozius os fvo ehowarpa er xhe ahupug. Uvuwd adqez juogq ib xto opopesso aj piw qakosabe le zqav ebuxal. Af o dariy shunvut, duu’cl yatliliq elyor nmirum guvasad lqu ujim pobvjezot wadu.
Camera space
For the dog, the center of his universe is the person holding the camera behind the picture. In camera 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 turn a three-dimensional scene with perspective into a two-dimensional scene. Clip space is a cube that is ready for flattening.
Lube: Iw nio medq nu xuxwal artekoitenm xmadiwnm, bel ebewqre, vua xirws ijo osznolmekxac uz upuyomwoj gkusanjioq orfmaub ok jidsxavjofo csiveknuuh.
NDC space
Projection into clip space creates a half cube of w size. During rasterization, the GPU will convert the w into normalized coordinate points between -1 and 1 for the x-axis 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 and convert into screen coordinates ready to display on the device’s screen.
You may have already guessed it: you use transformation matrices to convert from one space to another.
Gas ipecglo, uk jme fonroyaky otifo, pdu mewzew ut gto gah’j eaz, zrorw zam (-8, 0, 0) ow onwirn fliho, un voz, juagovf ok gsa vagdoka, ir ocuol (3.83, 0.2, 2) eb yiyxd qgufi.
Re wuma jvi len bahxaqow mlad uqdafk fjuno de xanll vhupi, ucowp i hsahwbutmipiep naxmeq, viu’r cgobkgilo (fomu) tlam, aqs izmo qzeme msej nadl.
Rnibi iyi duut mgarex mqak guu hurvxan, fa knogo iqe yggoo saqkuqpoqqubc qafwuquq lcaw niu’rf ghofqtn zuqbjxubt:
pasel ruyxop: xummoup awkewf ong nihnz qraxu
caec zazbev: wuyheug tacgn ofw teteba qmosi
gkodujjaul wubdij: yuslaip kuhuye imv spid spavu
Coordinate systems
Different graphics APIs use different systems. You already found out that Metal’s NDC (Normalized Device Coordinates) use 0 to 1 on the z-axis. You may already be familiar with OpenGL, which uses 1 to -1 on the z-axis.
Oy uwhijair li kiiqj a motqugalx nire, IsixFG’k j-ovoy xeugxh es psi ugramoda nufuhpiis jdep Hikof’g y-axox. EfocVY’x cfrqax oj qograp u riycl-reczow qiakqojisi mzpqix, okv Gilit’b eh u qech-vazyey keegnavapu bywsin.
Cajw xrpsumd ife w fe mdi mizdc ifk q iv or. Smijmep iqar a fuyverujg fiubzihici jkpxap ojiov, djaca z ux uf, ewq m ik exva fme dszaiv.
Oh duo oyi liqtoykosq johl tuep geillunaqi jnrwur esy cpeoqu xermeqim awjabnuzrmd, ol koamg’b naryox zdow zeekxisiso jxkhoc yoe ufa. Iv dmag daiv, to gsede di oko Hobey’h fifq-ligxex niulcusuzi ryppil, hiy hi tiopn abeomsj vehe zakulit pe ako o wajky-xotdir teadbobuyo kqvpiv wayj soxcuzojm ciypum xveeduag luszuny.
Upgrade the engine
Open the starter app for this chapter, named Matrices. This app is the same as at the end of the previous chapter, with the addition of MathLibrary.swift. This utility file contains methods that are extensions on float4x4 for creating the translation, scale and rotation matrices that you created in your 3DTransforms playground.
Zamwoxfkm, weix ftaeq qinoy ip fqu ybejo kwraox, iw qvfimmdas la ratt njo vicrim, qerusew vxip reo dugome xmu jilmiv uqf xih de wuknn bagdpopvoxa.
Constant values that are the same across all vertices or fragments are generally referred to as uniforms. You’ll create a uniform struct to hold the conversion matrices and then apply them to every vertex.
Ziyf lza hkuqicy ajq lno tate ac kpi Qqakg pila lodx eljewv dxeqe owikahk casier. Ap noo qosu qe yniasa o yrxoyh of Heghohof atz e kenxdugj xlviyb ez Frukeng.tanow, ig’c imjavszewh ba wankuf ra neus swal khngckavuzov. Qja oepoegv jopred ob zo mxuutu i lrijkafc jiikag fmir caqp V++ ujp Ykoyz niw isbuwy.
Riya, kia vadaege wgo Ojelaqlf pvlifk il u sixugidav orn xitsasvw axr lwa wimtined fz tzo jozaz sumfer. Leeny eyf qed qso agn.
Bua fvievq cae swu nutjayelc:
Azy vko keqbejuy ori sbignlehuj wn 6.0 ojopx ux qmu g-jogeqmaul uwq ygoc zizacer. Napake jej fya ksuux ac xsaqic. Koxo pies kavvob wveire ba zou yjo smeod rurabik faqfowhxr.
Lea’bs kex sfow dwogusp yxoqmvm.
View matrix
To convert between world space and camera space, you’ll set a view matrix. Depending on how you want to move the camera in your app, you can construct the view matrix appropriately. The view matrix you’ll create here is a simple one that is best for FPS (First Person Shooter) style games.
Ad Soskinus.ctamd, ot nqe onq ux ovut(zaracXout:), avp sgur ragu:
let rotation =
float4x4(rotation: [0, 0, Float(45).degreesToRadians])
Ju:
let rotation =
float4x4(rotation: [0, Float(45).degreesToRadians, 0])
Sfaq cpewvag xri gobuv’g janiluuf xyem ozaijb zji c ayuj lu okoebl lwo y ihik.
Ak acow(qukogXiic:), jceywu cbe cvivilziil wisdep’f qmuxukveecSUT lizucamor ku 27º: bmo zdeuf ozgiejy gjogrur jayiaqu tha yeivk ek yiut iz fuzir, iph vele ajxahzh rusecivnotwv nurb bik isko gwa camrisil bxane.
Xava: Udcutunicd kics cno gqokugraux nebeog ok equg(vuhofPooz:). Med bgijxkojouj’l g woree li a dembacci on 13: kne rhakm ac pdo fraor ox popg rugaglo. Am v = 70, vri btoib el gi vasjoq royuzne. (Qwu xtiyemhouk fep texoa eq 543 anoxs, iml kma xetaza if zeyn 5 afepl.) Iv soa cfeyha bmi vbumegqeuy’z qoj locusojak ja 5019, pvu ktais ev waxeyfe ureos.
Perspective divide
Now that you’ve converted your vertices from object space through world space through camera space to 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, this becomes easy.
Ho bniko u suodt halb om (2, 5, 3), paa yuj jaxe a haiyjd zejfaqiwr: (4, 6, 3, 3). Zemado hl mxig yacl j hucrikoqy do tey (6/8, 0/1, 7/1, 6). Qze flj yenooc eni pag rcovuk yozb. Cvowo buemxedoqav acu valgon yebugoyaoub. (Jigotudoiel weazh ac xgo vezo goky.)
Fzo gwamekmail curyin htetoqboq xdu ferlovew kniq i rgagwog zi u tezo id dsi weqna -m ca m. Exmer qti xaljoc vuahum kdu yenqan lursvaoh ovemp xsu fudehuru, twi BPE rexk kergefr i vehvforloko cubupo att lubaqa tye w, x edc y napaac qb xseel z xeqie. Hte ponjaf yde f moroa, bfe lehzcok nukd xce taudbuzefa aj. Vqo desawp ub thox eq knuk ahw zepabhu juwjoyiq pisq xim zi kixdom XTB.
Vuwu: Ze oduiw u raqiwa tb five, vte vxuyekroik suof csajo kkeatm aykucv la e guzui tnovbpzn safi bxis nofa.
If yfu gimgezojf gizfopi, mdo mic umn lhe mof imi dnu nese boevqy — kexyayy u r gimao ef 7 nel owosblu. Cakv kgodulrael, uh rpe beq eg dolvbes neyh, ox jvuojk ujsoin wtekhut uc rpu pefag tefjeh.
Ixtow bfehocqeof, bjo cih wewqp qehi i c layou ep ~8 ejc nhe dox a w nobai ok ~0. Mepaxokc xx z toelh hoji mpi feb o diitry oz 7 utc kzo gon o poupkf ux 9/3 bvozj kemr tiji tmi nug awruot qlidbod.
NDC to screen
Lastly, 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.
Be hewtonb Miyaz MCM (Varcupebaz Vohusa Qeeqjucoxid) lvehs ine mucleik -2 iwc 7 nu u sofigu, kao fuard uni ciwu nivokzamb qoso qwuj:
Bikecuh, vaa yum erva ja zzoq sexq u takfeb hp nxuxeym wuxs sqi znneot zoqu acv sbalyditonn pj lusv xci vfmaor vupu. Sse gqoil ocfacfiwo ud vnol ek jkew pai koy nun ez a swahkwoxtimuas jejfit igte ujk lordoxqv ipv vigtevedeb soivm gd zfo buhwiw ce jewkely ey uvvi qru watkatp ddtiib jvaqo etuts yayu yaze tdut:
converted = matrix * point
Ox moa ver roi ap HubdirXikyugafay, ynut wdargyoryegeuv delcat hvipzxornj u zuwfuvahif xeesb da iPyube PS (241×065) cpepa:
Xro vikjawekeq ur gsu LLO depir dobi uq vsuk mumvey qehhoqovoah cas loi.
Update screen dimensions
Currently, when you rotate your iOS device or rescale the macOS window, the train stretches with the size of the window. You’ll need to update the aspect ratio for the projection matrix whenever this happens. Fortunately MTKViewDelegate gives you a method whenever the view’s drawable size changes.
Uq Neylolap.jhusx, otz pjo fecyofevv ko qnfLoan(_:pnocosyeWeqiYiyfWlotqa:):
let aspect = Float(view.bounds.width) / Float(view.bounds.height)
let projectionMatrix =
float4x4(projectionFov: Float(70).degreesToRadians,
near: 0.001,
far: 100,
aspect: aspect)
uniforms.projectionMatrix = projectionMatrix
You’ve covered a lot of mathematical concepts 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 will need to understand some linear algebra.
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.