Projekt iz kolegija "Računalna grafika"
U ovom projektu biti će obrađen pojam antialiasinga
s naglaskom na teksture. Prije svega, kao uvodni dio,
biti će opisan antialiasing na običnoj ravnoj liniji. Nakon
toga će se priča proširiti na razinu tesktura i mipmapa.
Iz priložene slike odmah je vidljivo kako pojam
antialiasinga označava ublažavanje grubih i stepeničastih
linija i rubova. Iza toga stoji prilično jednostavan algoritam koji točno određenim pikselima dodaje ili oduzima
intenzitet boje. Kroz sljedećih nekoliko primjera će se
detaljnije opisati najbitniji algoritmi i razlika između istih.
Kako bismo bolje shvatili antialiasing potrebno je prvo razumjeti zašto se događa sami aliasing. Budući da je na računalu nemoguće prikazati savršeno ravne linije (kao što je linija na slici lijevo), potrebno je implementirati nekakav algoritam da tu liniju što vjerodostojnije prikaže na ekranu. Razlog je taj što sve mora proći kroz proces rasterizacije da bi se moglo prikazati na ekranu. Procesom rasterizacije se određuje boja svakog piksela. Postoji više različitih algoritama koji se mogu koristiti, a jednog od njih najjednostavnije je razumjeti promatrajući sliku desno. Preslika se "obris" originalne linije (zeleni pravokutnik) i zatim se razmatra od početka do kraja linije boja za svaki piksel. Ovaj jednostavan algoritam se naziva Bresenhamov linijski algoritam i koristi samo dvije boje u ovom slučaju, crnu i bijelu. Dakle, ako kroz neki piksel prolazi zeleni pravokutnik i ispunjava ga više od 50% tada će taj piksel biti obojan crnom bojom. U ostalim slučajevima pikseli će ostati bijeli. Upravo zbog toga se događa pojava kockastih i stepeničastih krivulja. Međutim, idući algoritam uspio je omekšati oštre rubove i ostvariti privid ublaženih rubova i linija.
Za razliku od prethodnog algoritma, Xiaolin Wu linijski algoritam koristi drugačiji princip koji će se objasniti na temelju priložene slike. Potrebno je povući dužinu koja spaja središta popunjenih piksela (0,0 i 1,6). Da su oni susjedni, ne bi bilo nikakvih problema. Međutim, ovi pikseli su udaljeni i postavlja se pitanje na koji način obojati piksele koji se nalaze između. Prema ovom algoritmu to se događa na način da se izračunava postotak odstupanja žute linije od prvog susjednog piksela (1,0). Ako postoji određeno odstupanje tada se tom pikselu smanjuje intenzitet obojanosti za taj postotak. Isti taj postotak dobiva onaj piksel prema kojem se dogodio odmak (piksel 1,1). Na isti princip se bojaju i ostali parovi piksela čije su vrijednosti oordinate 0 i 1. Postepeno se dolazi do piksela kod kojeg odstupanje linije prelazi 50% i to znači da će po prvi puta pikseli s vrijednošću oordinate 1 postati tamniji od svojih parova na oordinati 0. Moguće je i da na sredini par piksela bude jednako obojan, kako je i na slici prikazano. Naposlijetku se dolazi do piksela kod kojeg žuta linija prolazi kroz središte i koji je potpuno crn.
Nakon što su postavljeni temelji može se preći na same teksture i problem antialiasinga kod tekstura. Na temelju iduće slike (odnosno teksture) će kroz nekoliko zanimljivih primjera biti opisan taj problem. Ova tekstura je odabrana namjerno jer sadržava mnogo različitih boja razbacanih po teskturi. Iz istog razloga je nemoguće odgovoriti na pitanje kojom bojom bi bili obojani pikseli kada bi ovu 16x16 teskturu smanjili na veličinu 2x2 piksela. Trenutno postoji 256 piksela i nije moguće reći koja 4 odabrati da najbolje reprezentiraju originalnu teksturu. Zato dolazi do pojave aliasinga, flickeringa i pojava na ekranu koje su neugodne oku.
Kao rješenje tog i sličnih problema uvodi se pojam mipmapinga. Mipmapa je kolekcija slika koje su jedna od druge manje četiri puta. Na slici je prikazan mipmap za našu teksturu 16x16 (idući mip će biti 8x8 piksela, zatim 4x4 piksela itd). Pojednostavljeno, to znači da se moraju četiri piksela iz početne teksture prikazati samo jednim pikselom u susjednom mipu. To se događa automatski da se izračunava prosjek ta četiri piksela (zblendaju se) i dobiveni rezultat se prikaže u manjem mipu. Taj proces se odvija za sve četvorke piksela u velikom mipu da se dobije manji, dok se ne dođe do jednog piksela na kraju lanca. Upravo to se dogodi kada se u WebGL pozove naredba gl.generateMipmap, a izgenerirane mipove (dijelovi koji sačinjavaju mipmap) koristi GPU ako joj zatrebaju. GPU izračunava omjer između teksela i piksela. Teksel je jedan piksel originalne teksture. Ovisno o omjeru teksela i piksela GPU će znati treba li uzeti generirani mip niže rezolucije i koji točno. Međutim, što ako omjer ne odgovara nijednom predefiniranom mipu, što ako je taj omjer točno između dva predefinirana mipa? Tada GPU može izabrati jedan od dva susjedna mipa ili se može uvesti još jedan napredniji pojam - trilinear filtering. Trilinear filtering označava postupak linearne interpolacije između susjednih mipova u mipmapi. Time se rješava problem odabira mipa jer se dobije "prijelazni" mip koji najbolje reprezentira teksuturu u tom kontekstu. Potrebo je obratiti pažnju na to da dimenzije strukture budu višekratnici broja 2, i u horizontalnom i u vertikalnom smjeru. U suprotnom neće biti moguće izgenerirati mipmap jer GPU po defaultu očekuje višekratnike broja 2 da to može procesirati.
Primjer preuzet sa stranice WebGLFundamentals
(https://webglfundamentals.org/webgl/lessons/webgl-3d-textures.html)
WebGL može na šest različitih načina generirati mipmap i za svaku teksturu se može odabrati željeni texture filtering. Opcije su sljedeće:
Primjer preuzet sa stranice WebGLFundamentals
(https://webglfundamentals.org/webgl/lessons/webgl-3d-textures.html)
Na primjeru iznad možemo vidjeti šest traka koje su načinjene od prikazane teksture, međutim svaka traka ima različit način texture filteringa. Te opcije su primjenjivane redom kako su i nabrojane iznad. Prva traka koristi NEAREST način koja rezultira grubim i oštrim linijama bez prijelaza, a smanjenjem rezolucije se jasno vidi nastajanje distorzije. NEAREST opcija koristi samo glavni mip u mipmapi za odabir piksela u ostalim mipovima. Zbog toga su i vidljive nepravilnosti u nižim rezolucijama. To se jasno može vidjeti klikom miša na sliku koja prilikom čega dobivamo prikaz tekstura po korištenju određenog mipa. Vidljivo je da su prva i druga traka potpuno ljubičasto-bijele kombinacije. Druga opcija, LINEAR, isto koristi samo glavni mip ali koristi po četiri piksela iz tog mipa kako bi kreirao jedan piksel. Zato su prijelazi između boja unutar teksture mekaniji u odnosu na prvu traku jer se pikseli blendaju međusobno. Treća traka koristi NEAREST_MIPMAP_NEAREST i prva je koja koristi i ostale mipova, a ne samo prvi. Ona uzima najbliži mip i uzima samo jedan piksel iz tog mipa. Zato u obojanom prikazu točno možemo primjetiti prijelaz između dva mipa (između ljubičaste i plave, između plave i crvene itd). Isti takav prijelaz možemo vidjeti i na četvrtoj traci koja koristi LINEAR_MIPMAP_NEAREST jer isto koristi samo najbliži mip, ali uzima po četiri piksela iz tog mipa i blenda ih u jedan. Prva traka u kojoj se više ne vidi prijelaz između mipova je NEAREST_MIPMAP_LINEAR koja za svoje piksele koristi dva najbolja mipa, uzima po jedan piksel iz oba te ih blenda. Zato se više ne vide prijelazi između mipova, nego gradijentski prijelaz između boja. Očekivano, LINEAR_MIPMAP_LINEAR, funkcionira na isti način, ali uzima po četiri piksela iz oba mipa i sve ih blenda. Taj prikaz je najvjerodostojniji, ali je i definitivno najkompliciraniji i najskuplji što se resursa tiče.