Hemtenta i Grafik och Interaktionsprogrammering Martin Berglund 830130-0078 Uppgift 1 Jag har länge och väl funderat över på vilket sätt som vore bäst att beskriva vad jag har lärt mig under kursens gång och jag tror mig vara övertygad om att detta skulle vara att diskutera de olika föreläsningarna. Som en introduktion till det kan det vara lämpligt att komplettera med en redogörelse för vad jag bar med mig för kunskap om just grafik- och interaktionsprogrammering innan kursen startade. När jag väl hade lärt mig grunderna i programmering, en gång i tiden, så ville jag snabbt gå vidare mot att lära mig att skriva grafiska program. Jag provade några olika utvecklingsmiljöer med dialogeditorer och skapade enklare program. Därefter blev jag fascinerad av 3D-motorer och lärde mig OpenGL för att försöka skriva en egen. Men för att en 3D-motor ska vara meningsfull krävs innehåll och för detta så började jag skriva egna verktyg. Jag tröttnade någonstans där och började titta på andra grenar av datorvetenskapen. Men under tiden hade jag lärt mig DirectX och fått en viss förståelse av hur den matematik som ligger bakom 3D-grafiken fungerar. Fram till kursstarten hade jag ändå av och till arbetat med grafikprogrammering och kände mig väl förberedd. Föreläsning 1 kunde jag inte delta på grund av schemakrock, men jag hörde från andra att det var en intressant film som visades. Jag hoppas att kunna få se den någon annan gång. Föreläsning 2, som handlade om signalbehandling, tog upp sådant som jag inte tidigare kände till eller inte förstod. Jag kände att jag fick en bättre förståelse för färgmodellen och hur diskretisering av färg fungerar. Det här var en presentation av grafik på en så låg nivå som jag aldrig tidigare reflekterat över. På föreläsning 3, som handlade om 2D-grafik, kände jag mig ganska hemma. Tranformationerna och de andra matematiska elementen kände jag igen från 3D-världen och sprites var också bekant efter närmare studier av Super Nintendo-spel sen tidigare. Jag hade greppat hur interpolation över primitiver fungerar och även grafikarbete med lager. När det gäller transformation i 3D, som föreläsning 4 handlade om, så var det ett sedan tidigare bekant ämne, men jag upplevde det intressant att få förklarat på svenska. Min förståelse av vad som egentligen händer hade tidigare varit ganska begränsad och överlag kände jag att det var vissa element som jag inte förstod alls. Men på den här föreläsningen så kändes det som att allting slutligen kunde falla på plats och fylla upp alla hål. Gimbal lock är något som jag råkat ut för själv tidigare, men jag har aldrig förstått problemet eller ens vetat om att det hade ett namn. Jag kände att jag äntligen begrep vad kvaternioner är och vad de är bra för, tyvärr har jag än idag inte fått chansen att testa dem. När så föreläsning 5, första gästföreläsningen, anlänt så kände jag mig nog inte mer klokare när jag gick ut ur salen jämfört med när jag kom in. Att man kan experimentera sig fram till väldigt spännande bilder med Photoshop var jag sedan tidigare medveten om, föreläsningen tyckte jag inte tog upp särskilt mycket annat. Men nästa handlade om kurvor och ytor, föreläsning 6, och där kände jag till ungefär vad vi hade lärt oss i Numeriska Metoder-kursen. Mycket av matematiken som ligger bakom de olika kurvorna hade vi talat om i den eller flervariabel-kursen, men det var kul att få se demo:n på dem i realtid. Catmull-Clark-ytor kände jag inte till som begrepp och hade bara en
vag aning om att det borde gå att jämna till ytor på det viset. Det kände således spännande att få det förklarat i mer detalj och demonstrerat. Det kändes som någonting väldigt användbart. Föreläsning 7 beskrev rastrering och displayalgoritmer, här lärde jag mig de mer elementära delarna av 3D-rendering och de fundamentala algoritmer som ritar ut former på skärmen. Om detta kunde jag tidigare ingenting. När det gäller borttagning av skymda ytor så kände jag mig däremot mer hemma. Jag hade tidigare, från när jag ville skriva en egen 3D-motor, tittat på binärrymduppdelning och quad-träd, så jag var väl insatt i dessa algoritmer. Z-buffring kommer naturligt ur OpenGL, backface-culling likaså. Portaler och visibility-sets hade jag tidigare sett kod för men visste inte i detalj hur de fungerar. Jag kände under föreläsningen att jag ville göra något som använda detta som spelprojekt i sista labben (vilket mina kamrater dessvärre röstade ner). Billboards var jag bekant med, även om jag aldrig använt dem själv, men impostors var mig helt främmande. Jag blev väldigt imponerat av vad man kan åstadkomma och kunde inte låta bli att fundera över hur de konstrueras; för hand eller datorgenererade? Animation var temat för Föreläsning 8 och den började med morphing som jag givetvis kände till men inte alls visste hur det fungerade. Inverse kinematics är begrepp som jag stött på men inte visste vad det var. Jag funderade själv över liknande idéer när jag planerade min 3D-motor med jag visste inte alls om att det fanns en term för det. Jag började fundera på hur det kunde implementeras i real-tid och försökte tänka efter om jag sett det i real-tid någonstans (kunde inte komma på något, kanske är det inte vanligt?). Olika metoder av skinning kände jag inte heller till, men det är nog för att det rör sig mera in mot en konstnärliga delen av datorgrafik. Jag hade ingen aning om att kan försöker simulera muskler under huden på modellerna för att få realistiska kroppsanimationer. Fysikbaserade simuleringar hade jag tittat lite granna på tidigare via öppna bibliotek för fysiksimulering, så det kändes bekant. Partikelsystem kunde jag inte så mycket om däremot, så det kändes kul att lära sig teorin bakom och se vad man kan göra med det. När det gäller objektorientering, som föreläsning 9 handlade om, så kändes allting väldigt bekant eftersom jag programmerat i objektorienterade språk sedan länge. Informationsvisualisering, föreläsning 10, var däremot helt nytt med många nya begrepp. Det var en analys av datorgränssnitt på en så grundläggande nivå att jag inte reflekterat över det tidigare. Jag misstänker att mycket av detta kommer i MDI-kursen nästa höst. OpenGL var ju som jag tidigare skrivit bekant, så att jag var i Tokyo när föreläsning 11 hölls gjorde kanske inte så mycket. Av vad jag sett i föreläsningsanteckningarna i efterhand så verkade det vara sådant som jag tidigare arbetat med. Att jag fortfarande befann mig på andra sidan jordklotet och lyssnade på musik när föreläsning 12 om visualisering hölls var däremot kanske inte lika lyckat. Det var en föreläsning som jag annars gärna hade gått på. Föreläsningsanteckningarna gav tyvärr inte så mycket. Så kom bildsyntes till fokus i föreläsning 13 och denna gång var jag tillbaka i Sverige. Föreläsningen tog nästan enbart upp sådant som jag hört talas om tidigare men inte hade någon aning om hur det fungerade. Det kändes som en väldigt givande föreläsning eftersom jag kände att jag fick en bättre förståelse för framför allt ljusmodeller, vilket jag inte sysslat mycket med förut.
Det blev dags att ge sig på datorspel i föreläsning 14 vilket jag tyckte var väldigt kul. Den senare delen av datorspelshistorian var mig bekant, likaså de olika komponentera i ett datorspel, men det var ändå intressant att få allt förklarat på svenska. Shaders och andra specialeffekter som dök upp i sista föreläsningen, föreläsning 15, är ingenting som jag själv skrivit kod för, men jag har ändå försökt att förstå dem tidigare. Dessvärre hade jag aldrig riktigt förstått vad de skulle vara bra för förrän nu. Det var väldigt intressant och lärorikt att se på live-demonstrationen av olika belysningsmodeller och olika kod för hur enskilda pixlar kan manipuleras. Sammanfattningsvis kan jag säga att kursen har tagit upp mycket som varit mig bekant eller till och med känt, men ändå kompletterat med mycket nyttigt som jag inte tidigare kunnat eller bara har haft en vag aning om. Vissa av labbarna har varit mycket givande, andra väldigt frustrerande (*host* en-nivå-undo-director *host*) men jag har lärt mig mycket mer än vad jag trodde innan kursen började. Framför allt har den gett en bred och heltäckande kunskapsbas inom datorgrafik och interaktionsprogrammering.
Uppgift 2 Här ska jag beskriva ett av kursens teman i detalj och visa vilka koncept, metoder och tillämpningar som är centrala. Jag tycker att många ämnen som kursen tagit upp är intressanta och har velat lite mellan några olika. Men till slut har jag bestämt mig för att beskriva olika displayalgoritmer, i synnerhet borttagning av skymda ytor. Jag kommer att beskriva binärrymduppdelning, quad-träd, oct-träd och andra smarta knep. Ungefär lika länge som människan har försökt rita i 3D på datorer så har behovet av att kunna minimera antalet utritningar av polygoner funnits. Med lite smarta knep kan man bedöma om en polygon ligger helt och hållet utanför skärmen och därmed inte behöver ritas, men för att kunna vara riktigt effektiv ska man helst kunna döma ut hela grupper av polygoner redan innan de transformeras för utritning. Binärrymdsuppdelning är ett bra sätt att i förväg beräkna vad som syns och vad som inte syns beroende på vart kameran befinner sig. Att kombinera binärrymdsuppdelning med en tabell över vilka områden som skymmer andra områden ger en hög effektivitet och en god approximation till den optimala lösningen på problemet att rendera så få polygoner som möjligt. Det första större datorspelet som använde sig av binärrymdsuppdelning var Doom; där maximal prestanda var absolut nödvändig då datorerna som det var tänkt att fungera på inte var särskilt kraftiga. Nackdelen med binärrymdsuppdelning, kombinerat med synlighetsinformationen, är att genereringen tar väldigt lång tid för komplicerad indata (dvs, många polygoner, tätt). Dessutom kräver den konvexa polygoner (vilket kan åstadkommas med tesselation). Binärrymdsuppdelning fungerar enligt följande. Först väljer man en polygon ur mängden sätter den som första nod i en trädstruktur. Man tar sedan det plan som polygonen ligger i och sorterar in alla andra polygoner i en lista för de som ligger framför planet och en för de som ligger bakom. Alla polygoner som skär planet delas upp vid planets skärningspunkt till två polygoner, som hamnar i var sin lista. Därefter sätts listorna som två barnnoder till roten. Nästa steg är att rekursivt går igenom trädet och när man kommer till en nod med fler än en polygon i sin lista så väljer man en av polygonerna, sorterar in de övriga efter om de ligger framför eller bakom och hänger på listorna som nya barnnoder. På så vis bygger man upp ett binärt träd av alla polygoner. Den första effekt man får ut av detta träd är att man kan rita ut alla polygoner i ordning, sorterat efter vilken som är längst bort. Detta sker genom att man tar kamerans position och kontrollerar mot översta nodens plan. Är kameran framför planet ska man traversera trädet först till noderna bakom översta noden, därefter rita noden och sist traversera till noderna framför översta noden. Är kameran placerad bakom planet gör man tvärt om. Processen upprepas för varje nod som besöks. På så vis är man garanterad att inte rita över en polygon som är nära kameran med en som ligger längre bort. Men detta fixar sig ändå på våra modernare grafikkort som har hårdvarustöd för Z-buffring. Men trots det kan det vara användbart, exempelvis om vi vill rendera flera genomskinliga ytor så måste ytan längst bort renderas först. Men, målet var ju att kunna välja bort grupper av polygoner som vi vet inte syns. Inga problem, vi kan använda kamerans frustum för att välja bort delar av trädet. Detta går till genom att när vi traverserar trädet så kollar vi om varje nods plan korsar kamerans frustum. Om den inte gör det, och kameran är placerad framför planet, kan vi hoppa över helt att rita ut allt bakom noden. På
samma sätt, om vi är bakom planet och kamerans frustum inte korsar planet kan vi hoppa över att rita ut allting framför. Som en ytterligare bonus till trädet som skapas kan vi använda det för mer än bara rendering, det fungerar för kollisionsdetektering, pathfinding, sektorsindelning och säker ännu mer. En nackdel är tyvärr att binärrymdsuppdelningen lämpar sig bäst för inomhusscener. För utomhuslandskap där den mesta av geometrin ligger (nästan) horisontellt duger den inte så bra, då får vi ta till andra metoder. Moderna 3D-applikationer idag kanske inte heller behöver vara så noga. Vi har mer minne, mer processorkraft och kraftigare grafikkort. Ett annat sätt att sortera geometri på som är mindre tidskrävande att räkna på vid generering men ändå fungerar bra på att välja bort ytor som inte syns är önskvärt. Man kan då ta till quad-träd eller oct-träd. Ett quad-träd är en indelning av världen i ett rutnät, sett uppifrån. Man börjar med fyra stora rutor som delar in världen i fyra lika stora delar. Polygoner som går över gränsen mellan två rutor får man dela på. Därefter tar man varje ruta och delar i sin tur upp dem i fyra mindre rutor. Processen upprepas tills dess att man når ett önskat minimivärde på rutstorlek. När man sedan ska rendera geometrin kontrollerar man vart kameran befinner sig och vilka rutor som kamerans frustum antingen korsar eller helt inkluderar. Man börjar med de fyra stora rutorna och väljer bort de som är helt utanför. De som korsar kamerans frustum får man gå ner på nästa nivå rutor och testa dem. Om en ruta är helt inkluderad renderar man den helt och hållet utan att traversera mer. För den lägsta nivån av rutor får man rendera även dem som skär kamerans frustum. Quad-trädet är effektivt men behöver ytterligare information om vilka rutor som är skymda när kameran står i en viss ruta (dvs, skymda fast innanför kamerans frustum) för att bli riktiga bra. Oct-träd är en utökning där man delar även i höjdled, det vill säga att världen delas upp i kuber istället för rutor, 2x2x2 = 8 kuber som startfall och därefter i mindre kuber. Om geometrin sträcker ut sig åt alla håll är detta en mer effektiv lösning. Men för utomhus-scener räcker förmodligen quad-trädet. För alla objekt som inte tillhör den statiska geometrin kan man också vilja välja vilka som ska visas. Ett enkelt sätt är att ge objektet en bounding-box eller en bounding-sphere och ta reda på om denna befinner sig inom kamerans frustum. Om man måste hantera många objekt kan man associera dem med vilkan ruta/kub de befinner sig i för tillfället och bara rita dem om rutan/kuben ska ritas. Är alla rutor/kuber lika stora (vilket de bör vara!) så är det lätt att ta reda på vilken ruta/kub ett objekt befinner sig i med enkel division av objektets position. Utöver dessa tekniker får man ta till en del listiga knep för att ta bort ytterligare ytor. Om man inte har genererad information om vilka ytor som är dolda med hänsyn till kamerans position så kan man lägga in denna information manuellt, kanske inte för alla områden med för några väl utvalda. En tidigt använd teknik för att dölja geometri som ligger långt bort från kameran är att använda en dimma som döljer allting efter ett visst avstånd. Med oct-träd eller quad-träd kan man då enkelt kolla avståndet till varje ruta och avgöra om den ska ritas eller inte. Jag har här kort diskuterat några olika metoder för att dela upp geometri och på ett effektivt sätt kunna döma ut polygoner redan innan de transformerats. I takt med utvecklingen av hårdvara har applikationerna också ökade i komplexitet på grafiken, så dessa algoritmer är i högsta grad fortfarande aktuella.
Uppgift 3 Jag ska här föra en diskussion kring datorgrafikens betydelse för datorspel i alla dess former, eftersom jag känner att det är datorspel jag kan mest om, av de relevanta kulturella fenomen som jag kan tänka mig. För ett datorspel idag så betyder grafiken oändligt mycket. Det är grafiken som är det första vi ser och det som vi i första hand använder för att jämföra olika spel. Grafiken måste upprätthålla en viss nivå för att överhuvudtaget kunna ha en chans att kunna komma ut på marknaden (med vissa undantag som bekräftar regeln). Den här nivån av vad man förväntar sig av ett modernt datorspel blir givetvis högre ju mer tiden går och den stenhårda konkurrensen inom datorspelsindustrin trissar upp kraven ännu mer. Om ett spel tar två år att utveckla så måste man alltså redan från början kunna sikta på vilken hårdvara som konsumenterna kommer att använda när spelet är färdigt och budgetera grafiken därefter. Historiskt sett så har grafiken givetvis inte alltid varit tyngdpunkten i datorspel, för de datorer som enbart kunde visa text så fanns ju även datorspel. Men så fort grafik i sin mest primitiva form blev tillgänglig så började datorspelen att bli den flitigaste användaren av detta. I takt med att datorerna blivit snabbare har också grafiken blivit mer avancerad, två händelser som jag minns väl var när datorerna plötsligt kunde använda SVGA och när 3D-acceleratorerna kom ut på marknaden. Någonstans emellan dessa två punkter kom Windows 95 till hemmen och det grafiska gränssnittet för de (minst) kommande 15 åren blev definierat. Det första datorspelet som jag provade med SVGA var SimCity 2000, som såg mycket imponerande ut även om jag då inte riktigt kunde sätta fingret på vad som var nytt. Men inte bara grafikkorten har bidragit, när ID Softwares spel Quake kom ut kunde man visa att för full 3D-rendering i realtid behövdes ungefär en processor i 100 Mhz och 8 Mb RAM. Senare, när jag lärt mig programmera och börjat experimentera med DirectX märkte jag av när Microsoft valde att lägga ner 2D-komponenten DirectDraw och istället enbart fokusera på 3D. Grafikkorten hade blivit så bra på 3D att 2D gick snabbare att emulera än att ge något speciellt stöd för. Tyvärr kunde grafiken också bli för mycket, när CD-skivor började bli vanliga försökte vissa att göra spel som mest bestod av film där det gällde att klicka sig rätt under filmens gång. Det visade sig inte vara någon bra idé. I spelet Duke Nukem Forever envisades man med att hålla sig till den senaste grafiken vilken innebar att grafikmotorn blev utbytt flera gånger med stora förseningar som resultat. Efter nästan 9 år av utveckling är spelet fortfarande inte klart. Datorgrafiken idag anser jag att man fortfarande bearbetar på samma sätt. Det är omgivningen som sätter gränserna på vad vi uppfattar och hur vi uppfattar det, på så vis kommer vi nog aldrig att bli mätta på bättre och häftigare grafik. De spel som kom till Super Nintendo var oändligt mycket vackrare än de som fanns till föregångaren NES, men idag skulle vi inte tycka att det var något märkvärdigt. Idag har den stora strömmen datorspel en strävan efter att vara så realistiska som det bara går, grafiskt sett. Tidigare har en del spel försökt att vara realistiska i sin spellogik, men grafikhårdvaran har först nu blivit så bra att vi kan börja tala om en grafisk realism. Tyvärr är det fortfarande långt att gå, Oblivion behöver den allra senaste grafikhårdvaran för att fungera tillfredställande med alla effekter påslagna, men klarar ändå inte av att rendera stora landskap på ett effektivt sätt. Men ingenting tyder på att det kommer att göras avkall från denna linje, vi kommer förmodligen att få se fler försök under de närmsta åren. Jag skulle vilja efterlysa spel där datorgrafiken inte måste vara perfekt utan kan få vara bara datorgrafik. Det finns ingenting som säger att ett spel som inte kräver den senaste hårdvaran inte är lika bra som de andra. Fortfarande idag kan man spela äldre spel och uppskatta dem, även om grafiken inte håller sig med dagens mått. Nintendo har exempelvis fortfarande hållit kvar vid sin egna stil. Istället för att gå mot en högre realism har man låtit de tvådimensionella figurerna vuxit till sig i 3D och låtit dem använda 3D-grafiken för att hitta
nya sätt för spelaren att styra och spela. Super Mario 64 satte verkligen upp standarden för hur platformsspel i 3D ska se ut och fungera och än idag är det svårslaget. Ett datorspel idag förväntas kunna visa skuggor, en trovärdig ljussättning, ytor som är bumpmappade, trovärdigt vatten och annat av samma komplexitet. Mycket av detta kräver ett grafikkort med stöd för shader-program och mycket processorkraft vilket gör att enbart en dator med någorlunda ny hårdvara kan spela det. Men om vi ser på detta, och det ökande kravet på realism, så inser man att ray-tracing i realtid är vad vi försöker simulera. Det är alltså inte alls helt otroligt att nästa stora händelse inom datorgrafiken blir hårdvara för att göra riktig ray-tracing i realtid, förmodligen med datorspel som första tillämpare. För grafiker finns idag redan redskapen för att skapa närmast fotorealistiska bilder genom 3D-modellering, att översätta dem till 3D-spel idag innebär en stor förlust eftersom rasteriseringsmodellen inte alls fungerar som ray-tracingmodellen. Senare tids programmerbara grafikkort ger visserligen möjlighet att behålla en del av dessa specialeffekter, men ray-tracing skulle inte bara göra det lättare utan också lösa många andra problem, såsom skuggor, skymda ytor, genomskinlighet och anti-aliasing. Redan idag finns några implementationer av ray-tracing i realtid, till och med en prototyp på ett grafikchip som renderar ray-tracing i hårdvaran. Så jag undrar om inte framtiden bär hitåt. En annan utmaning för realistisk datorgrafik är avsaknaden av djupseende. Så länge vi tittar på en platt bild på skärmen så vet vi att bilden inte är realistisk. Men trots att man länge har kunnat använda olika sätt för att separera ut bilder för de olika ögonen så har stereografiska vyer aldrig varit populära. Kanske är det för att vi inte vill bli lurade, att det häftiga med djupseende i en dator går över efter ett par dagar. Men jag anser att det ändå är värt att utforska inom den närmsta tiden, och det av följande anledningar. Först och främst så krävs adekvat hårdvara. För att kunna tro på det man ser krävs att ögonen blir inneslutna och har en bred synvinkel. Dessutom måste bilden vara tydlig och inte flimra. Givetvis måste bilderna för ögonen vara stereoseparerade. Dessa krav har fram tills nu ganska nyligen varit alldeles för hårda på de huvudmonterade skärmarna. Antingen har de varit på tok för dyra eller inte alls uppfyllt kraven. Därefter måste prestandarn kunna bibehållas. För att stereoseparering ska fungera ordentligt måste varje ruta ritas två gånger, vilket ger en halverad bildhastighet. Således måste grafikhårdvaran vara snabb nog. Sen anser jag att huvudtracking med gyro är nödvändigt. För att lura ögonen måste världen omkring en förändras som man förväntar sig. Att spåra riktningarna i 3 graders frihet har varit både dyrt och krångligt, dessutom har inget datorspel haft ett ordentligt stöd för det. I bästa fall är det integrerat i den bärbara skärmen. Jag skulle inte satsa miljoner på VR men personligen skulle jag gärna forska mer om det. Vidare så är jag nyfiken på vad som väntar datorspelsvärden i form av ljusomfång. Med skärmar som kan visa ett bredare spektra av ljus så kan realismen givetvis ökas, oavsett om rasterisering eller ray-tracing ligger i botten. Jag har sett annonser för Plasma-TV med kontrast på 10000:1, det skulle vara intressant att se datortillämpningar på detta och datorspel som kan hantera det fullt ut. Jag har här redogjort för datorgrafikens betydelse för datorspel, både då, nu och snart. Mina sista ord om datorgrafik i datorspel är att grafiken inte kan bli mer realistisk än vad grafikerna kan lyckas göra den. Det har vi åtminstone en väldefinierad gräns.