Tecniche di filtraggio: Antialiasing II parte.

Nella scorsa puntata erano state sommariamente descritte le principali forme di aliasing ed erano state introdotte nozioni di carattere teorico sugli algoritmi di antialiasing. Oggi si farà cenno alle tecniche adottate in concreto, sui chip grafici, per tentare di ridurre questo tipo di disturbi.

Iniziamo subito col dire che le tecniche comunemente utilizzate fanno ricorso ad algoritmi di sovracampionamento con filtraggio di tipo lineare o bilineare, operanti a livello di screen space. Aggiungiamo alcune considerazioni sul comportamento dell’occhio umano, che possono aiutare a capire meglio la natura di certe scelte a livello progettuale. In particolare, è opportuno specificare che il sistema occhio-cervello è più sensibile a disposizioni simmetriche e ordinate di elementi.

Inoltre il livello di sensibilià è maggiore lungo determinate direzioni o, per meglio dire, per determinati angoli (il che ha influenzato, come si vedrà in futuro, anche le scelte relative alle implementazioni del filtro anisotropico). In particolare. dividendo lo schermo in quattro quadranti, con gli assi X e Y lungo le direzioni verticale ed orizzontale, si è rilevato che è più facile notare artefatti lungo le direttrici relative agli angoli multipli di 45° (assi e bisettrici dei quadranti).

Questo significa che se si vuole mascherare un artefatto, è opportuno farlo utilizzando distribuzioni di “rumore” che non seguano le direttrici indicate.  Non a caso, ho parlato di “rumore”, poichè, di fatto, un’operazione di filtraggio dei tipo di quelle menzionate introduce dei disturbi che servono a mascherare altri disturbi.

Fatta questa premessa, cerchiamo di capire come agisce un algoritmo che opera un sovracampionamento dell’immagine.  Di fatto, si prende ciascun pixel dell’immagine originale o di parte di essa, lo si scompone in una serie di subpixel, si compiono alcune operazioni con questi subpixel e, infine, si riporta l’immagine alle dimensioni originarie.  Ciò che contraddistingue un algoritmo da un altro è la modalità di scelta delle posizioni, del numero dei subpixel (ovvero del tipo di pattern) e delle operazioni che si compiono su di essi.

point-sampling.bmpIl metodo più semplice di filtraggio è il POINT SAMPLING, in cui si ha campionamento 1:1 tra immagine originale e immagine “filtrata”.

In pratica, si immagina come se i valori di LUMINANZA (Y) e CROMINANZA (C) del pixel, fossero concentrati in un punto e tutto il pixel assumesse una distribuzione di Y e C uniforme, data proprio da quei valori. Ovviamente questo metodo è ben lungi dall’eliminare gli artefatti, soprattutto se si sceglie sempre come riferimento il centro del pixel. Le cose migliorano se si effettua un’operazione di point sampling facendo ricorso a pattern di tipo fully jittered, come in figura

point-sampling-jittered.bmp

per quanto detto circa la sensibilità dell’occhio umano alle distribuzioni uniformi. In pratica, un pattern di tipo random come quello proposto qui sopra,  ha lo scopo di introdurre del “rumore bianco” che maschera i disturbi da aliasing. Nei fatti, l’utilizzo di un solo sample per pixel non è molto utile e migliora solo di poco la situazione rispetto ad un’operazione di sampling con distribuzione ordinata.

2x-og.bmpLe cose migliorano, ma non in maniera drastica, scegliendo 2 campioni per pixel; anche in questo caso vale il discorso relativo alle distribuzioni simmetriche e alle direttrici fatto in precedenza; quindi la scelta migliore è quella di un pattern di tipo 2x jittered, la peggiore è quella rappresentata in figura .

Di fatto, però, 2 campioni sono troppo pochi per generare una cifra di rumore bianco accettabile per mascherare la meglio l’aliasing nel caso di ditribuzione jittered, e risulta altrettanto difficile percepire i benefici di una scelta, ad esempio, di una griglia di tipo ROTATED rispetto ad una di tipo ORDERED (come le due in figura).

Con questi due termini abbiamo introdotto altrettanti nuovi concetti che risulteranno più chiari quando si inizierà a parlare della modalità 4x, ovvero con 4 sample per pixel.

A questo punto, è opportuno aprire una parentesi per introdurre altri nuovi concetti: in particolare le definizioni di Full Scene AntiAliasing (FSAA), Edge AntiAliasing (EAA), MultiSampling AntiAliasing (MSAA) e SuperSampling AntiAliasing (SSAA).

Per farlo, scendiamo un po’ più nel dettaglio delle operazioni di “campionamento e ricostruzione” dell’immagine, partendo da quello che alcuni definiscono approccio di tipo brute force, ovvero il SSAA.  Tralasciando la modalità 2x, come detto, poco efficace, mi limito a fare l’esempio di ciò che accade con l’applicazione del SSAA 4x.

Per ogni pixel si individuano 4 subpixel e, per ciascuno di essi, si calcolano i valori di Y e C relativi. I valori ottenuti vengono interpolati tra di loro, fino ad ottenere un unico valore che sarà una media, pesata o meno a seconda del tipo di algoritmo, di questi 4 campioni. La scelta della griglia di campionamento e ricostruzione può essere fatta in diversi modi con differenti livelli di efficacia. Qui di seguito, sono riportati gli esempi di Ordered Grid SSAA e di Rotated Grid SSAA

Img1

Il primo ad essere implementato è stato l’OG SSAA, in quanto più semplice da implementare. Il SSAA RG, infatti, prevede un ulteriore passaggio prima dell’output, ovvero la rotazione della griglia del filtro ricostruttore. Questa operazione può essere affetuata servendosi di buffer supplementari, detti accumulation buffer, il cui utilizzo, però, prevede che l’operazione di jittering, ovvero di rotazione, avvenga via software con notevole impiego di bandwidth.

3dFX, con la Voodoo 5, risolse il problema abbinando agli accumulation buffer un circuito che si occupava dell’operazione di interpolazione e rotazione in hardware e inviava i campioni filtrati direttamente alla ramDAC. In modalità SSAA 4x, i due VSA-100 operavano su 2 sample ciascuno e i rispettivi valori erano immagazzinati in altrettanti T-buffer e ricombinati immediatamente a monte della ramDAC. In tal modo si risparmiava banda passante e non si avevano immagini alla display resolution nel frame buffer. La tecnologia in oggetto permise a 3dFX di ottenere un’eccellente implementazione dell’antialiasing, superiore a quella della concorrenza a parità di “costo computazionale”.

Il SSAA presenta, però, degli inconvenienti. Innanzitutto è applicato a tutta la scena (FSAA) e, di conseguenza, risulta molto pesante a livello di calcoli, richiede molto spazio all’interno del frame buffer, spreca molta bandwidth. Inoltre, l’azione di un filtro di questo tipo è quella di impastare i colori, attenuando le brusche transizioni di C e Y (corrispondenti a frequenze di segnale elevatissime). Questa azione, da un lato attenua i disturbi da aliasing, dall’altro, agendo anche dove non serve, fa perdere profondità all’immagine. Le soluzioni sono diverse: l’utilizzo di algoritmi più sofisticati di semplici interpolazioni lineari; l’adozione di filtri più selettivi.

La strada che si è seguita, dopo la generazione dei chip DX7, è stata la seconda.

Fanno così la loro comparsa gli algoritmi di tipo MSAA che non agiscono più sull’intera immagine ma solo sui bordi dei poligoni.

Il principio del MSAA è analogo a quello del SSAA ma, in questo caso, per ogni pixel si selezionano n sample, disposti secondo la griglia prevista dal tipo di algoritmo scelto,  e si attribuisce a tutti il valore di Y e C del pixel d’origine. Questo tipo di filtro è meno raffinato rispetto al SSAA e la sua azione di attenuazione delle transizioni è meno efficace. In maniera grossolana, potremmo dire che l’azione principale di questo filtro è quella di ispessire quei bordi dei poligoni in cui compaiono le scalettature, riducendo la visibilità di queste ultime. Anche per il MSAA esistono le due modalità OG e RG, come appare in figura, dove il pixel originario è quello blu al centro e i subsample i 4 rossi.

msaa-og-e-rg.bmp

Da questa immagine appare chiaro uno dei motivi per cui una griglia di tipo rotated risulta più efficace di una  di tipo ordered: si raddoppia il numero di assi percepiti in ogni direzione (le linee verdi che passano per i subpixel); in tal modo diminuisce la loro reciproca distanza aumentando la sensazione di “confusione” percepita. In pratica si inganna meglio il sistema occhio-cervello, sfruttando i limiti del potere risolutivo spaziale del primo e la capacità di ricostruire l’immagine anche con dati parziali da parte del secondo.

Per cercare di ottenere prestazioni migliori senza penalizzare troppo la qualità, nVIDIA introduce un tipo di MSAA RG denominato Quincunx il cui principio di base è molto semplice: simulare un algoritmo di tipo RGMS 4x utilizzando due soli sample. Il risultato è quello in figura

Img2

Come si vede dalla prima immagine, per ogni pixel sono generati 2 subpixel; nella seconda figura si hanno in totale 4 pixel  e 8 subpixel scelti in posizione tale per cui ognuno fa da subpixel per gli altri circostanti. In realtà questo algoritmo produce effetti migliori rispetto ad un MSAA OG 4x e di poco superiori ad un MSAA 2x di tipo jittered, ma non è comparabile ad un 4x RGMS anche perchè i subpixel sono allocati lungo direttrici poste a 45° con gli assi X e Y.

Sempre in tema di algoritmi di MSAA, invece, ATi  con il suo Smoothvision introduce, per la prima volta, un pattern di tipo fully jittered

jittered-msaa.bmp

Con questo tipo di griglia si possono ottenere risultati paragonabili o superiori a quelli di un MSAA RG anche se 4 sample per pixel sono ancora in numero insufficiente per generare la quantità di white noise sufficiente ad ottenere un filtraggio ottimale.

Gli algoritmi di tipo MSAA, come detto, applicano il filtro in maniera selettiva agendo solo sui bordi dei poligoni; sono filtri di tipo  BOX e devono essere affiancati da algoritmi di edge detect che agiscono a livello di depth-buffer. Nel prossimo articolo approfondiremo alcuni di questi concetti e seguiremo l’evoluzione degli algoritmi di antialiasing, con un cenno ai filtri bilineari ed alla loro attuale implementazione, a quelli che fanno uso di fully jittered grid con un numero elevato di sample e a ciò che prevedono le nuove API.

Press ESC to close