# 4 Optimizacija programa za sjenčanje ## 4.1 Zašto provoditi optimizaciju programa za sjenčanje Razlog za optimizaciju programa za sjenčanje je što je ponekad brzina kadra (eng. *frame rate*) jako niska. Niski broj kadrova u sekundi (eng. *frame-per-second* ili kraće *FPS*) je primjetan ako se igra naizgled sporo ponaša. Ako je broj kadrova dovoljno nizak, igranje igre može se činiti kao da se prikazuje dijaprojekcija jer se samo nekoliko različitih kadrova pojavljuje na ekranu u sekundi. U manje ekstremnim slučajevima igra će dati osjećaj trzavosti i sporine - upravo suprotno od glatkosti, kako bi i trebalo biti. Problemi s brojem kardova u sekundi nisu uzrokovani problemima s mrežom. Ako postoji niska brzina kadrova, to nije igra koja zaostaje - to je računalo koje ne uspijeva pratiti igru. Korisniku će možda trebati brža grafička kartica, više RAM-a (skraćeno za eng. *Random Access Memory*) ili bolji CPU. Također, tvrdi disk može biti prespor, što dovodi do usporavanja igre jer je prisiljen čitati podatke s tvrdog diska. Možda u pozadini radi previše softvera koji se natječu za resurse. Drugim riječima, nizak FPS problem je u performansama igre na računalu. A u problemu performiranja igre na računalu veliku ulogu imaju programi za sjenčanje, davajući veliku potrebu za optimizacijskim metodama. https://www.howtogeek.com/142193/htg-explains-why-lag-and-low-fps-arent-the-same-thing/ ## 4.2 Metode mjerenja učinkovitosti programa za sjenčanje Kako bi smo znali koje tehnike provesti i na koji način optimizirati programe za sjenčanje, prvi korak koji moramo napraviti je izmjeriti koliko su ti programi uopće učinkoviti i koliko se dobro provode. Postoji više načina kako mjeriti učinkovitost programa za sjenčanje. S obzirom na potrebe korisnika svaka metoda se može koristiti pojedinačno, no u praksi bi najtočnije očitanje bilo provesti sve metode kako bi se korisnik uvjerio da je stanje jednako u svim metodama. ### 4.2.1 Način prikaza složenosti programa za sjenčanje Prva metoda je kroz *način prikaza složenosti programa za sjenčanje*. Ovoj opciji korisnik može pristupiti na način da se klikne na gumb *Lit*, zatim *Optimization Viewmodes* te nakon toga *Shader Complexity*. **SLIKA - MeasuringShaders1** Ova opcija na ekranu pokaže scenu u obojanom stanju. Scena će biti obojana u boju ovisno o programu za sjenčanje; na dnu ekrana može se vidjeti skala sve od impaktne zelene boje sve do bijele boje. Boje označavaju koliko je objektov program za sjenčanje kompliciran i težak za provođenje. Što je više objekata na sceni obojeno zeleno, to je program za sjenčanje manje zahtjevan. Objekti obojeni u kričavo crveno sve do bijele boje, to je program zahtjevniji i valjalo bi ga optimizirati. **SLIKA - MeasuringShaders2** U našem slučaju, naša scena se sastoji od objekata koji još nemaju teksture, te iz tog razloga je sve zeleno i optimalno. No, kada bismo dodali neke početničke teksture u sceni, izgled i rezultat ovog mjerenja bio bi sitno drugačiji. **SLIKA - MeasuringShaders3** **SLIKA - MeasuringShaders4** S obzirom da su dodane teksture iz UE-ovog početničkog paketa objekata, programi za sjenčanje su sitno zahtjevni te razlika sa ili bez tekstura nije velika. Ako bismo učitali već gotovu scenu koja je besplatno dostupna na Epic Games tržištu, vidjeli bismo veliku razliku. **SLIKA - MeasuringShaders5** **SLIKA - MeasuringShaders6** U ovoj sceni programi za sjenčanje nisu optimizirani te su jako zahtjevni, što se može pročitati iz ružičaste boje koja se nazire na sredini scene, označavajući jako lošu optimizaciju. Međutim, ova metoda nije savršena iz razloga što daje samo generalnu ideju toga koji program za sjenčanje može biti teži za provođenje te se uvelike oslanja na broj instrukcija koji mora izvršiti za svaki program za sjenčanje. Uz to, ne daje detalje o tome što konkretno stvara problem u programu za sjenčanje da bismo ga znali optimizirati. ### 4.2.2 Broj instrukcija Sljedeća metoda kojom se može mjeriti koliko je program za sjenčanje zahtjevan je *metoda broja instrukcija*. Sjetimo se velike prednosti kod UE alata, a to su *Blueprints*, vizualni sistem programiranja. Ovaj sistem također funkcionira sa teksturama i programima za sjenčanje. Ako želimo pobliže promatrati neku teksturu, UE alat ju otvori u zasebnom prozoru i pokaže detalje o toj teksturi. **SLIKE - MeasuringShaders7** Ovdje vidimo graf sa čvorovima koji sadrže intrukcije rada za programe za sjenčanje. Kada složimo svoj graf sa čvorovima on se kompilira u HLSL kod, nakon čega se taj kod kompilira u asemblerske instrukcije, nakon čega se te instrukcije šalju grafičkom upravljačkom programu i grafičkoj kartici. Dakle, ako znamo koliko asemblerskih instrukcija naš program za sjenčanje sadrži, možemo ocjeniti njegovu zahtjevnost i jednostavnost provođenja. To nas vodi do zaključka da, ako bismo uspjeli smanjiti broj instrukcija u programu za sjenčanje, dobili bismo bolje optimiziran program za sjenčanje. U našem slučaju, možemo vidjeti da ova konkretna tekstura sadrži 145 instrukcija. **SLIKE - MeasuringShaders8** Nažalost, ni ovo nije savršena metoda za ocjenu zahtjevnosti iz razloga što sve instrukcije ne zahtjevaju jednako vremena za izvođenje na GPU-u, te nam to ne garantira brže provođenje programa za sjenčanje. Isto tako, svaka platforma zahtjeva različiti način kompiliranja, što može rezultirati u različitom broju instrukcija na svakoj platformi. ### 4.2.3 Testiranje projekta na različitim platformama Najtočnija metoda za mjerenje optimalnosti programa za sjenčanje je testirati projekt na različitim platformama. Iako je najtočnija, ova metoda je i najteža za koristiti jer zahtjeva puno pripreme. Potrebno je postaviti program za sjenčanje na objekt, objekt postaviti u scenu u kojoj se program za sjenčanje koristi, izvesti projekt kao gotovu igru te nakon toga testirati na raznim platformama. Prednost koju nodi ova metoda je ta da svaka platforma ima drugačije karakteristike za provođenje programa za sjenčanje. Na taj način možemo dobiti precizno očitanje sa svake platforme za isti program za sjenčanje u istoj sceni, sa istim akcijama i postavkama, i vidjeti koliko je program za sjenčanje optimalan. Mana ove metode uz dugotrajnu pripremu je ta što nema svaki korisnik pristup platformama na kojima želi izvesti svoj projekt. Zato bi uvijek bilo optimalno prvo pripremiti neki način na koji će se projekt testirati na drugim platformama prije nego što se projekt finalizira. ## 4.3 Metode optimizacije programa za sjenčanje Nakon što smo utvrdili koji program za sjenčanje stvara poteškoće i koliko, sljedeći korak je optimizirati taj program. Ovisno o problemu koji postoji, birati će se jedna od metoda optimizacije. ### 4.3.1 Rješavanje nepotrebnih karakteristika Kao vrlo jednostavna metoda, program za sjenčanje može postati optimalniji na način da se izbrišu pojedine karakteristike iz njega koje su nepotrebne i zauzimaju određen broj instrukcija koje ne služe ničemu. Na primjer, ako u grafu s čvorovima programa za sjenčanje postoje opcije poput iscrtavanja crnih uzoraka koji bi bez te opcije i dalje bili crni, ta opcija je beskorisna i može se maknuti. Kao još jedan primjer možemo pogledati jedan od početnih programa za sjenčanje koji dolazi sa UE besplatnim paketom na početku. **SLIKA - Optimising1** Na slici možemo vidjeti kako program za sjenčanje ima posebni skup naredbi za *Large scale tiling*. Opcija *TexCoord* stoji skraćeno za *TextureCoordinate*, odnosno koordinate teksture. Ona daje koordinate UV teksture u obliku dvokanalne vektorske vrijednosti, s kojima daje mogućnost mijenjanja skale pločica koje će se pokazivati na sceni te koliko će veliko pločica izgledati na pojedinom objektu. Ovaj skup opcija će jedino biti nužnost ako ovu teksturu stavljamo na objekt velike površine. Broj *0.05* stoji kao konstanta kojom će se množiti vrijednosti koordinata u slučaju da su velike, kako bi manipulacija položaja teksture bila što lakša. No, s obzirom na naš slučaj, ovu teksturu koristimo na malim objektima, te nam je taj skup opcija nepotreban. **SLIKA - Optimising2** Kada bismo izbrisali cijeli skup tih naredbi za skaliranje, ne bismo vidjeli nikakvu razliku. **SLIKA - Optimising3** **SLIKA - Optimising4** Česti su slučajevi gdje korisnik koristi vrlo napredan program za sjenčanje, no od 17 mogućih iskoristivih opcija korisnik ugasi 15 opcija, te mu ostanu samo dvije opcije aktivne. U tom slučaju program za sjenčanje je i dalje opterećen svim opcijama, bez obzira što se u toj sceni ne koriste. Puno optimalnije bi bilo izbrisati neiskorištene opcije kako bi se zahtjevnost programa za sjenčanje smanjila, čak i kada su te opcije ugašene u sceni. ### 4.3.2 Prerada matematičkih formula Ponekada se u programima za sjenčanje koriste matematičke operacije za jednostavniju manipulaciju teksturom. Ono što korisnici najčešće ne uzimaju u obzir je da neke matematičke funkcije zahtjevaju više snage nego ostale. Najbolja opcija kod rada sa matematičkim formulama je probati postići svoj cilj sa što manje zahtjevnim operacijama, npr. zbrajanje, oduzimanje, množenje i dijeljenje. Sve operacije iznad toga su zahtjevnije i troše više vremena. Uzmimo za primjer ovaj program za sjenčanje. **SLIKA - Optimising16** Ovdje imamo program za sjenčanje koji imitira realističnu teksturu kamena sa mahovinom u prirodi. Ovaj efekt postignut je na način da se koriste maske. Maske nasumično stvaraju vrijednosti u rangu između 0 i 1, gdje 0 predstavlja kamen (crna boja), a 1 mahovinu (bijela boja). **SLIKA - Optimising17** S obzirom na to koju vrijednost maske proizvedu, dalje se koristi matematička funkcija potenciranja kako bi se odredilo gdje će se prikazivati kamen, a gdje mahovina. Što je vrijednost bliža nuli, to će biti više kamena, te isto vrijedi za jedinicu i mahovinu. Ikakva vrijednost između nule i jedinice proizvodi gradijentni prijelaz. U prirodi se neće dogoditi lagani prijelaz iz kamena u mahovinu, nego oštar prijelaz bez gradijenata. Kako bismo to osigurali, moramo imati što više vrijednosti blizu nule i blizu jedinice, a što manje vrijednosti koje teže sredini. Međutim, sama operacija potenciranja je poprilično zahtjevna, te je potrebno više vremena da se izvede. Uz to, ne pruža dobar način za manipulacijom omjera koliko se mahovine nalazi na vrhu kamena. Ako bismo smanjili vrijednost potencije sa 100 na 1, dobili bismo ovakav slučaj. **SLIKA - Optimising18** Ne samo da postoji veliki gradijentni prijelaz između mahovine i kamena, već nam se pozicija mahovine proširila po cijelom objektu, što nama nije poželjno. Ovo se može izbjeći na način da se iskoristi novi, manje zahtjevan set matematičkih funkcija. S obzirom da maske proizvode svoje nasumične vrijednosti u rasponu od 0 do 1, možemo staviti operaciju oduzimanja 0.5 sa te početne vrijednosti, pomnožiti ju s nekim cijelim brojem, te vratiti tih oduzetih 0.5. Ovime je osigurano da, koji god broj dobili natrag, biti će ili ispod nule ili iznad jedinice. Maske samo gledaju kojem broju je vrijednost blizu, što znači da se svi minusi računaju kao nula, i svi brojevi iznad jedinice kao jedinica. **SLIKA - Optimising19** Dakle, rezultat je dobar i precizan. Ako pogledamo pobliže broj instrukcija, nakon ovih operacija imamo manji broj instrukcija nego prije, bez obzira što su tri odvojene matematičke funkcije. Ovime možemo zaključiti da smo zaista optimizirali program za sjenčanje preradom matematičkih funkcija iz više zahtjevnih u jednostavne. ### 4.3.3 Kombiniranje komponenata, manje matematike Metoda kombiniranja komponenata služi za postići rezultat sa manje matematike i varijabli, a s tim i manje zahtjevnosti. Ako postoji način da identičan segment naredbi pojednostavimo mijenjanjem tipa varijabli, program za sjenčanje je uredniji i jednostavniji. Za ovu metodu optimizacije programa za sjenčanje možemo koristiti primjer na sljedećoj slici. Ovdje možemo vidjeti program za sjenčanje koji predstavlja distorziju. Sadrži se od dvije teksture koje koriste komponentu vizualni šum, odnosno *noise*. Taj šum postoji kako bi distorzirao UV koordinate programa za sjenčanje, te se sve na kraju spaja u treću teksturu. **SLIKA - Optimising5** Bitno je za primjetiti da je početni dio s dvije teksture ovog programa za sjenčanje duplikat. Jedina razlika su konstante koje ulaze u teksture. Dakle, unosimo različite vrijednosti, no sve ostale karakteristike su iste. **SLIKA - Optimising6** Korisniku koji cilja na optimizaciju svog programa za sjenčanje ovakav slučaj je znak za to da postoji način za ovo pojednostaviti kako bi smanjio zahtjevnost programa za sjenčanje. Najviše komputacijski zahtjevan dio u ovom primjeru su matematičke funkcije množenja i zbrajanja, odnosno *multiply* i *add*. Neovisno o tome što su te funkcije malo zahtjevne, s obzirom na cijeli program za sjenčanje troše najviše snage. Cilj optimiziacije je što više smanjiti potrošnost. U ovom slučaju to možemo napraviti na način da kombiniramo te dvije teksture u jednu te promijenimo tip varijable kojim unosimo svoje vrijednosti konstanti. Trenutno se konstante pohranjuju u tipu float2. Na početku programa za sjenčanje vrijednosti gornje linije naredbi pohranjuju se u X i Y kanal UV koordinata, a donje u Z i W. **SLIKA - Optimising7** Način na koji ovo možemo promijeniti je stvoriti novu varijablu tipa float4 gdje ćemo pohraniti sve vrijednosti koje su originalno spremljene u dvije različite float2 varijable. Kako je potrebno imitirati prijašnju dodjelu varijabli određenim koordinatama, postoji funkcija *AppendVector*, koja omogućuje kombiniranje kanala za stvaranje vektora s više kanala od originalnog. Dakle, korištenjem te funkcije možemo iste vrijednosti dodijeliti istim koordinatama kao prije na puno uredniji i manje zahtjevan način. Na kraju, možemo razdovijiti te kanale u dvije maske koje nam predstavljaju teksture s kojima smo počeli na početku, no na puno kompaktniji način. **SLIKA - Optimising8** ### 4.3.4 Pakiranje kanala teksture Primjerak teksture je jedna od najzahtjevnijih karakteristika programa za sjenčanje. Kada god postoji više primjeraka teksture koji koriste isti UV kanal, najisplativije je kompresirati ih sve zajedno u jednu teksturu da postoji što manje instrukcija u asemblerskom kodu. Na sljedećoj slici možemo vidjeti primjer jednog takvog programa za sjenčanje koji koristi više primjeraka teksture. Redom; boja, metalnost, refleksija, gruboća, mapiranje teksture i ambijentalna okluzija. **SLIKA - Optimising9** Koristimo pet različitih primjeraka teksture, te time radimo 102 insturkcije asemblerskom kodu. To je poprilično malo instrukcija, ali može biti i manje. Ono što možemo napraviti je korisiti neki vanjski alat za manipulaciju slikama, npr. Photoshop, kako bismo spojili sve primjerke teksture zajedno u jednu teksturu. Naime, Physically Based Rendering teksture (kraće PBR teksture) koriste mnogo crno-bijelih slika, što možemo vidjeti i u našem slučaju. Unutar alata poput Photoshopa vrlo je jednostavno umetnuti određene primjerke tekstura u R, G, B kanale (Red, Green, Blue kanale). S obzirom na poziciju primjeraka u kanal, alat za stvaranje igara može koristiti određeni kanal kao primjerak teksture. Pogledajmo kako to izgleda na ovom primjeru. Umjesto pet različitih primjeraka teksture, napravili smo komprimaciju u jednu teksturu sa R, G, B kanalima. Ako pogledamo samo crveni kanal, vidjeti ćemo primjerak ambijentalne okluzije. **SLIKA - Optimising11** Ako pogledamo samo zeleni kanal, vidjeti ćemo primjerak refleksije. **SLIKA - Optimising12** Ako pogledamo samo plavi kanal, vidjeti ćemo metalnost. Naime, na kamenju nema metala, dakle metalnost je postavljena na vrijednost 0, te izlazi kao potpuno crna slika. **SLIKA - Optimising13** Ako pogledamo samo Alpha kanal (predstavlja informacije o transparentnosti po pikselu), vidjeti ćemo primjerak gruboće. **SLIKA - Optimising14** Ovime smo postigli spajanje četiri primjerka teksture u jednu. **SLIKA - Optimising10** Ovisno o kanalu gdje je koji primjerak teksture postavljen, spajamo odgovarajuće primjerke na odgovarajuće pozicije UV kanala. **SLIKA - Optimising15** Tekstura izgleda jednako kao što je izgledala i prije ove akcije, a naš cilj je postignut; program za sjenčanje sada javlja da imamo 100 instrukcija u asemblerskom kodu, za razliku od prije gdje smo imali 102 instrukcije. Iako je mali napredak, pri stvaranju igre koristi se mnogo različitih programa za sjenčanje i tekstura. Kad bismo dozvolili da svaki od tih programa ima dvije instrukcije previše zbog manjka optimizacije, zahtjevnost igre bi eksponencijalno narasla. Kako bismo to izbjegli, ovo je jednostavan način za osigurati se da su programi za sjenčanje što manje zahtjevni.