di  -  mercoledì 15 aprile 2009

Nello scorso articolo avevamo iniziato a descrivere le tecniche di antialiasing utilizzate dai produttori di chip grafici e si era visto come l’approccio iniziale avesse privilegiato le soluzioni di tipo FSAA, con l’adozione di tecniche di supersampling. Queste tecniche risultavano molto pesanti dal punto di vista computazionale, motivo per cui si è deciso di seguire un approccio diverso che potesse garantire risultati qualitativamente apprezzabili, soprattutto nei confronti di un tipo particolare di aliasing, quello definito jagged o stairstep, senza penalizzare troppo le prestazioni. La soluzione è stata quella di ricorrare all’utilizzo di multisampling che non è un tipo di FSAA, in quanto è applicato solo sui contorni delle figure.

Avevamo, altresì, visto come nelle tecniche di SSAA ogni pixel introduceva n valori di colore, altrettanti di tipo z/stencil, e almeno altrettanti facenti parte di una coverage mask utilizzata dal filtro ricostruttore del segnale. Nel MSAA si riduceva lo shader overhead, in quanto ad ogni pixel non corrispondevano n subpixel di colore differente ma n subpixel dello stesso colore.

Nell’ottica del cercare di conciliare qualità e prestazioni, avevamo anche visto un tentativo di nVIDIA di ottenere una griglia di campionamento di tipo 4x utilizzando solo 2 sample per pixel, denominato Quincunx. La tecnica consisteva nell’utilizzare i sample dei pixel vicini, anch’essi con 2 campioni ciascuno, per ottenere pattern 4x.

Se il Quincunx può essere schematizzato con la frase: fatti prestare un subpixel dai tuoi vicini, un’altra tecnica, volta ugualmente ad ottenere un numero n*2 sample utilizzando n campioni, può essere schematizzata con la frase: fatti prestare n sample dal frame successivo. Questa tecnica, adottata da ATi con la serie R4x0, è nota come Temporal AntiAliasing (TAA) e si tratta, ancora una volta, di una tecnica di antialiasing di tipo spaziale, ovvero che agisce sui pixel, da non confondere con le tecniche atte a combattere le forme di aliasing temporale.

Facciamo cenno al principio di funzionamento del TAA: in modalità 4x, nel frame 1 venivano presi 2 sample per pixel. Lo stesso si faceva nel frame 2, successivo, scegliendoli in modo tale che dalla composizione dei 4 subpixel risultasse un pattern di tipo RGMS. Anche in quuesto caso, come per il quincunx, si otteneva una griglia 4x facendo uso di 2 soli campioni per pixel. Per il TAA esisteva anche una modalità 8x ed una 12x che sfruttavano i pattern del MSAA box 4x e 6x del chip. In questo caso, non si ricorreva a griglie di tipo rotated ma di tipo fully jittered grid (FJG).

taa.bmp

Il risultato era una cosa del tipo di quella illustrata nella successiva immagine, dove alle prime due colonne corrispondono le immagini del frame dispoari e pari rispettivamente ed alla terza quella risultante. Il caso raffigurato è relativo alla modalità MSAA 4x, ovvero TAA 8x.

taa-esempio.bmp

A questo punto, è il caso di fare un paio di digressioni, una riguardante la tipologia di griglia adottata, l’altra il principio su cui si basa la tecnica del TAA.

Per quanto riguarda la scelta della griglia, il motivo per cui, in modalità MSAA 2x, si adotta una RGMS e non una  FJG risiede nel fatto che la seconda presenta una distribuzione casuale dei campioni. Questo, con 2 soli sample per frame e con, in totale, 4 sample, può provocare un’allocazione degli stessi sample non molto efficiente né ai fini della riduzione degli artefatti e neppure ai fini dell’individuazione dei bordi dei poligoni, necessaria in caso di applicazione di MSAA. Per un motivo analogo, ovvero la scarità di sample ai fini delle operazioni di edge detect, si vedrà come, nell’applicazione del CFAA, il filtro funziona solo abbinato alle modalità di MSAA 4x o superiore e non, ad esempio, con il 2x.

Riguardo al principio di funzionamento del TAA, questo si basa sul cosiddetto potere risolvente temporale dell’occhio umano . L’occhio è in grado di vedere come distinte, due immagini che si susseguono con un intervallo di tempo superiore ad 1/10 di secondo. Quindi, ad esempio, con frame rate inferiori a 10 fps si percepiscono due immagini fisse distinte e non si ha l’illusione del movimento.  Quindi, sembra sufficiente avere un frame rate di poco superiore ai 10 fps per non avere scatti. Questo significa che, in teoria, per avere immagini prive di scatti e con la riduzione dell’aliasing, facendo ricorso al TAA, è necessario avere frame rate superiori ai 20 fps. Ciò è vero in parte, in quanto la visione dell’occhio non va assimilata ad un sensore che cattura un’intera immagine ad ogni “scatto”, quanto piuttosto ad uno scanner che cattura, ad ogni scatto, parti dell’immagine che sono ricomposte dal cervello. Detto in maniera molto semplice, questo avviene perchè la parte dell’occhio che presenta la massima acuità visiva, la fovea, presenta un angolo di visuale di circa un grado a cui, però, corrisponde la maggior estensione della parte di corteccia deputata all’elaborazione delle immagini. Si tratta di una minuscola finestra di della cui esiguità non ci accorgiamo perchè l’occhio compie continui movimenti infinitesimi alternati a delle pause di fissazione. Durante queste pause, avviene il processo di cattura dell’immagine vero e proprio, mentre durante i movimenti, detti saccadi, la cui durata è pari a circa 1/4 di quella della corrispondente pausa di fissazione, la visione viene oscurata per evitare le scie tipiche che si vedono quando, ad esempio, si tenta di catturare un’immagine con un dispositivo la cui velocità di acquisizione è inferiore a quella del movimento dell’oggetto da catturare. Quindi, per circa un quarto della nostra della nostra vita da svegli, siamo di fatto ciechi senza che ce ne accorgiamo.

Un meccanismo di cattura così articolato, fa si che la qualità delle immagini percepite con un frame rate di poco superiore ai 10 fps non sia eccellente, benchè priva di scatti. Motivo per cui, ad esempio, nell’industria cinematografica si utlizza un frame rate di 24 immagini al secondo a cui si abbinano anche tecniche di motion blur.

Tornando al nostro TAA, appare evidente, a questo punto, che per avere una buona qualità d’immagine, non sia, dunque, sufficiente, tenere il frame rate poco sopra i 20 fps. Questo è il limite più evidente di questa tecnica che può funzionare bene solo a condizione di tenere frame che non scendano mai al di sotto dei 25-30 fps.

Rispetto al quincunx, questa tecnica garantisce risultati superiori, potendo, per altro, contare sulla copertura dell’intero frame e su pattern con elevato numero di sample in modalità FJG (che abbiamo visto essere qualitativamente la migliore), ma presenta condizioni di utilizzo piuttosto restrittive e non sempre applicabili.

Discorso a parte, che esula da una trattazione  relativa al 3D ma che rappresenta, comunque, una forma di antialiasing, è il Glyph Antialiasing di Matrox, che opera sui caratteri, in applicazioni 2D.  L’algoritmo si basa su un meccanismo di riconoscimento dei caratteri, correzione del gamma, sovracampionamento, filtraggio di tipo box e riduzione dell’immagine alle dimensioni originali, in maniera non dissimile da come agiscono gli algoritmi di MSAA con edge detect, in ambito 3D. L’accelerazione è interamente di tipo hardware

Introdotti i concetti di base sulle tecniche di filtraggio e terminate le digressioni sui tentativi di adottare tecniche che permettessero di arrivare a compromessi tra qualità e prestazioni,  facciamo, ora, qualche cenno alle tecniche di antialising adottate sulle attuali gpu.

Sia ATi che nVidia fanno uso di di MSAA box con edge detect abbinate a tecniche di filtraggio delle texture trasparenti. Queste ultime, così come gli algoritmi di tipo bilineare (i TENT) di ATi, sono di tipo FSAA, mentre il MSAA, in tutte le sue varianti, è di tipo EDGE ANTIALIASING.

Sia nVidia che ATi prevedono le classiche modalità 2x, 4x e 8x del MSAA box, con le prime due che fanno uso di griglia di tipo rotated e la terza che utilizza una griglia di tipo fully jittered, come riportato di seguito

msaa-2x.bmp2x    msaa-4x.bmp4x    msaa-8x.bmp 8x

I chip nVidia della serie G8x e GT2x0 implementano altre modalità di AA che vanno sotto il nome di Coverage Sample AntiAliasing (CSAA). La differenza rispetto al MSAA di tipo classico è che questa modalità fa uso di una griglia di tipo misto, parte della quale ricavata dai valori del campionamento effettuato per le operazioni di MSAA, che permettono di immagazzinare valori relativi ad ogni pixel, nello z e nello stencil buffer parte ricavata, in fase di ricostruzione del segnale, attraverso una coverage mask che permette di creare altri sample. Questo permette di ridurre l’accoppiamento tra z/stencil value e subsample della coverage mask, riducendo, di conseguenza, l’occupazione di banda e i costi di storage.

In pratica, ad esempio, la modalità 8x fa uso dei 4 sample del MSAA 4x più altri 4 sample disposti secondo una FJG generati in fase di ricostruzione del segnale. In questo modo, i costi di campionamento e storage sono quelli di un 4x con una qualità intermedia tra il tradizionale MSAA 4x e il MSAA 8x.

nvidia-8x.bmp  In figura, i puntini neri sono quelli della griglia del MSAA 4x, quelli blu sono quelli aggiunti dalla coverage mask del CSAA.

Tra le altre modalità segnalo la 16x e la 16xQ che è quella qualitativamente migliore proposta da nVidia.

nvidia-16x.bmp 16x      nvidia-16xq.bmp 16xQ

Coeme si vede, la prima fa uso di  una modalità mista 4x RGMS + 12x CS (coverage sample), mentre la seconda fa uso di 8x FJGMS + 8x CS.

In casa ATi le proposte sono analoghe e quella che cambia è il tipo di coverage mask. Le nodalità di MSAA con edge detect proposte, sono le classiche 2x, 4x, 8x MSAA e le  due relative al CFAA (custom filtering antialiasing).

Come nel caso di nVidia, queste modalità funzionano solo se abbinate a MSAA box con almeno 4 sample; questo perchè 2 subpixel sono troppo pochi per poter fare efficacemente un’operazione di edge detect. La prima delle due modalità è definita 4x EDGE-DETECT  AA e presenta una griglia di tipo misto con 4x RGMS + 8x CS, la seconda è la 8x  EDGE-DETECT AA e presenta una griglia 8xFJGMS + 16x CS. Anche in questo caso, i sample supplementari sono aggiunti a livello di coverage mask.

Questa tecnica permette di avere un filtro ricostruttore con un numero di sample sensibilmente più elevato a costo computazionale comparabile  a quello di un MSAA box 4x o 8x.

Da notare che la modalità 8x MSAA è stata inrtodotta con la generazione dx10; R5x0 e GT7x, infatti, arrivavano rispettivamente ad avere un 6x RGMS il primo e un 8xS il secondo, che era una modalità ibrida con RGMS 4x + 2x OGSS, il cui impatto sulle prestazioni era piuttosto elevato, contenendo anche una componente di SSAA che, come sappiamo, è di tipo FSAA. Questo limite derivava dal limite nel numero dei render target  su cui era possibile “scrivere” i valori dei sample ottenuti nelle operazioni di MSAA.

Con la generazione DX9 era stata introdotta anche una modalità di filtraggio delle texture trasparenti, ribattezzata Adaptive AA da ATi e Transparent SSAA da nVidia.  Si tratta, in entrambi i casi, di algoritmi di SSAA applicati alle sole texture “trasparenti” ovvero quelle contenenti elementi troppo minuti per poter essere correttamente rappresentati senza artefatti. Questo tipo di AA segue le regole del SS tradizionale e serve combattere, più l’effetto a “gradini” quello che si definisce polygon popping, ovvero l’effetto rappresentato microscopicamente nella seguente figura

polygon-popping.bmp

che si riscontra quando gli elementi da rappresentare sono sensibilmente più piccoli degli stessi pixel (fogliame di un albero, rete metallica, ecc).; il risultato  a livello macroscopico è quello rappresentato in figura

adaptive-aa.bmp

dove, nell’immagine di destra è applicato anche un adaptive o un transparent AA, mentre in quella di sinistra il solo MSAA 4x box.

Le DX9 hanno portato delle innovazioni a livello di filtraggio, ma presentavano anche dei limiti. Oltre quello già visto sul numero si sample utilizzabili per il MSAA, un altro limite, sempre connesso al numero di render target utilizzabile per le operazioni di z-buffering, impedisce l’uso di MSAA con engine che fanno uso di tecniche di deferred rendering. Questo perchè, come abbiamo visto, gli algoritmi di MSAA si appoggiano ai dati contenuti nello z-buffer. Le operazioni di deferred rendering prevedono la rimozione di tutte le superfici nascoste prima delle operazioni di rendring. Questo significa che solo parte dei dati relativi alle posizioni dei vertici dei poligoni lungo l’asse z, contenuti nello z-buffer, sono conservati, ovvero quelli dei poligoni che non vengono rimossi. Ciò significa che se le RBE sono in grado di applicare il filtro AA sul frame in corso di elaborazione (in quanto l’operazione avviene prima della rimozione dei poligoni stessi), non sono in grado di farlo su quelli successivi, poichè non hanno più accesso ai dati che erano contenuti nello z-buffer e eono stati cancellati in seguito alle operazioni di HSR. Questo obbliga le unità geometriche a ricalcolare le geometrie per ogni frame e rende inconciliabili le operazioni di MSAA con il deferred rendering. Il problema è stato aggirato con le DX10, grazie a due tecniche: la prima prevede che i dati contenuti nello z-buffer, prima delle operazioni di HSR, siano salvati su una texture, in modo da poter essere richiamati all’occorrenza facendo un’operazione di accesso a texture. Il secondo, più elegante ed efficace a livello di impatto sulle prestazioni, dà la possibilità di inizializzare un color buffer come z o depth buffer, in modo da utilizzarlo per conservare i dati dello z-buffer. La soluzione definitiva arriva dalle DX10.1 che prevedono l’utilizzo di tanti render target per lo z-buffer quanti se ne ha bisogno, ciascuno con la propria modalità di rendering.

Con questa frase introduco un altro dei limiti dell’attuale tecnologia basata sull’utilizzo delle RBE o ROP’s per l’applicazione del MSAA. Le RBE contengono un circuito dedicato all’applicazione del MSAA box che opera a 8 bit di tipo INTEGER, il che limita la precisione di calcolo e, se può andar bene per  algoritmi di tipo BOX, non è sicuramente funzionale ad algoritmi più sofisticati che fanno uso di funzioni  di ordine superiore al primo.

Infatti, sia le DX10 e, ancor più, le DX10. 1  e le future DX11, prevedono l’adozione di filtri di tipo custom con algorimi non lineari calcolati dalle unità di shading.

Un ultimo, brevissimo, appunto riguarda l’aliasing temporale che si manifesta sotto forma di strobing e flickering. Il primo si ha, ad esempio, quando si sottocampiona un oggetto che ruota sul proprio asse, come nell’esempio sottostante

strobing.bmp

dove nella prima riga appare l’oggetto che ruota, mentre nella seconda si hanno i campioni prelevati in caso si usi una frequenza pari ad 1/34 di quella di ritazione. Come si vede, la ruota appare girare in senso contrario a quello in cui effettivamente si muove.

Il secondo si manifesta con rapidi cambi di colore o piccoli oggetti oppure linee sottili che sembrano apparire e scomparire tra un frame ed il successivo.

Esistono vari metodi per combattere questi tipi di aliasing che vanno dal sovracampionamneto che, però, come nel caso dell’aliasing spaziale, non sempre è possibile o risolve il problema, all’utilizzo di operazioni di convoluzione con filtri passabasso per ottenere segnali limitati in banda.

L’approccio più comune è, però, analogo a quello seguito per l’aliasing spaziale: se le tecniche di spatial antialising applicano una sorta di blurring a livello di pixel, le tecniche di temporal antialiasing applicano il blurring a livello di frame. Esistono vari modi per ottenere il motion blur. Il più comune e anche l’unico cui farò cenno, è quello che fa uso di sovracampionamento temporale dell’immagine, alla stregua di quanto avviene con il SSAA di tipo spaziale. Ad esempio, se un oggetto si sposta di una distanza pari a 16 pixel in un secondo, sarà sufficiente campionare a 16 frame (o anche meno) al secondo e interpolare le immagini ottenute, immagazzinate all’interno di accumulation buffer.

Le tecniche di antialising spaziale e temporale sono, nella maggior parte dei casi, combinate tra loro ed utilizzate insieme ad altre tecniche di filtraggio (ad esempio quelle che interessano le texture) per ottenere la miglior qualità d’immagine possibile, sia che si tratti di giochi che di programmi di grafica 3D e, come abbiamo visto, anche di applicazioni di tipo desktop.

10 Commenti »

I commenti inseriti dai lettori di AppuntiDigitali non sono oggetto di moderazione preventiva, ma solo di eventuale filtro antispam. Qualora si ravvisi un contenuto non consono (offensivo o diffamatorio) si prega di contattare l'amministrazione di Appunti Digitali all'indirizzo info@appuntidigitali.it, specificando quale sia il commento in oggetto.

  • # 1
    TheFoggy
     scrive: 

    Una cosa: alla fine, quando parli del Motion Blur..forse intendevi dire “Ad esempio, se un oggetto si sposta di una distanza pari a 16 pixel in un secondo”, invece di “Ad esempio, se un oggetto si sposta di una distanza pari a 16 pixel in un frame”, vero? C’è anche da dire che la tecnica di SS per il MB, è devastante per le prestazioni, nonostante sia DX che OGl forniscano una funzione per il salvataggio nella RAM del front buffer..
    Ne approfitto per ribadire i miei complimenti per quanto riguarda questi articoli!

  • # 2
    yossarian (Autore del post)
     scrive: 

    grazie per la segnalazione, ho provveduto a correggere.
    Si, la tecnica del SS è devastante e non solo per il MB, motivo epr cui, sia per l’AA spaziale che temporale sono state messe a punto tecniche alternative.
    Sarebbe stato utile poterne parlare più diffusamente ed in maniera più approfondita, ma lo spazio a disposizione è limitato e l’argomento pare essere un po’ troppo “tecnico” per i più (anche se mi sono sforzato di essere il più discorsivo possibile) e ho cercato, più che altro, di fare una panoramica molto generica sulle tecniche di AA adoperate nel corso di questi anni.

    Ti ringrazio per i complimenti ed anche per le segnalazioni d’errore

  • # 3
    shodan
     scrive: 

    Ciao yossarian,
    innanzitutto complimenti per l’articolo.

    Volevo farti una domanda: nel caso del CSAA, non ho molto chiaro da dove vengano presi i campioni della coverage mask. Vengono costruiti in modo “autonomo” nelle rop?

    Ciao.

  • # 4
    yossarian (Autore del post)
     scrive: 

    @ shodan

    Innanzitutto ben ritrovato.
    I sample della coverage mask sono in parte ricavati dal campionamneto, in parte generati dalle rop’s con modalità random. I primi sono disposti secondo una griglia di tipo rotated (fino a 4 campioni) e una griglia di tipo pseudo jittered per l’8x; i secondi hanno una disposizione del tutto casuale.

  • # 5
    shodan
     scrive: 

    Ciao yossarian,
    c’è una cosa che non capisco…

    Nel caso del MSAA 4X, l’immagine viene effettivamente renderizzata a una risoluzione 4 volte maggiore (anche se poi ai subpixel viene assegnato lo stesso colore). Va da se, quindi, che per poter generare più sample l’immagine viene in effetti sovracampionata.

    Nel caso del CSAA 8X, diciamo in configurazione 4X (MSAA)+ 4X (CSAA), mi pare di capire che l’immagine _non_ viene renderizzata a una risoluzione 8 volte superiore, ma solo di 4 volte maggiore (in pratica per la componente MSAA). Ammesso che siano le rops a generare i 4 sample CSAA rimanenti, come fanno se non hanno a disposizione altri subpixel? Alzano “temporaneamente” la risoluzione del fragmento (da 1 pixel ne ricavano 4) usando sempre lo stesso colore del fragmento stesso e spostando in modo randomico i 4 sample così ottenuti, per poi ricongiungere tutto in un unico pixel?

    Ciao,
    grazie!

  • # 6
    yossarian (Autore del post)
     scrive: 

    @ shodan
    scusami se non ti ho risposto prima, ma sono stato occupatissimo con il lavoro.

    C’è da distinguere tra il CSAA di nVidia ed il CFAA di ATi. Il primo fa uso, ad esempio, nel caso da te citato, di 8 sample del MSAA box delle rop’s e di 8 punti ricavati secondo uno schema predeterminato atto a individuare la posizione del subpixel analizzato rispetto ad un eventuale triangolo che può coprirlo per intero, in parte o per nulla. Al contrario di quanto avviene per i subsample del MSAA di cui vengono trasmessi i valori relativi al colore ed alla posizione z del sample, nel caso del csaa si trasmettono solo informazioni relative all’intersezione di quel determinato sample con un determinato triangolo. In caso ci sia intersezione si trasmette il valore 1 e si ricava un sample dai valori di color/z/stencil di quel triangolo; altrimenti si trasmette il valore 0 e non si hanno sample aggiuntivi.
    Diverso il caso del CFAA di ATi che fa uso di pattern più estesi rispetto alle dimensioni del sample, prendendo a “prestito” subpixel dai pixel contigui (in maniera analoga a quanto faceva il quincunx). In questo modo il CFAA, contrariamente a quanto avviene per il CSAA, è trasparente all’applicazione e genera un superiore numero di sample; però risulta più pesante.

  • # 7
    Stefem
     scrive: 

    Ciao yossarian, le modalità CSAA non fanno uso di: la 8x 4 Color/Z/Stencil sample + 8 Coverage Sample, la 8xQ 8 C/Z/S sample + 8 CS, la 16x 4 C/Z/S sample + 16 CS e la 16xQ 8 C/Z/S sample + 16 CS?

  • # 8
    yossarian (Autore del post)
     scrive: 

    @ Stefem

    No, I valori 8x, 16x, ecc indicano il numero complessivo di sample tra quelli selezionati in fase di sampling del MSAA box tradizionale e quelli ricavati dalla coverage mask.
    La difefrenza qualitativa, ad esempio, tra 16x e 16xQ è data dal maggior numero (8) di sample derivanti dalle operazioni di campionamento del MSAA della 16Q rispetto alla 16x normale e dal fatto che in caso di 16xQ 4 di questi sample sono disposti in modalità jittered (se guardi, in effetti, i 4 neri vicino ai bordi sono disposti secondo una rotated grid ruotata di 45° in senso orario rispetto a quelli della modalità 16x). Si vede anche dalle figure relative ai due algoritmi di campionamento (i punti neri sono i sample ricavati dal MSAA e quelli blu i sample della coverage mask).

  • # 9
    Stefem
     scrive: 

    @yossarian
    ok, ma i valori che ho postato li ho letti in un documento, forse presente nell’SDK, in cui si spiega come implementare il CSAA in DX9 e DX10, anche se magari ricordo male.

  • # 10
    yossarian (Autore del post)
     scrive: 

    @ Stefem

    forse ti riferisci a questo
    http://developer.nvidia.com/object/coverage-sampled-aa.html

    In quel caso, è fuorviante la tabella che riporta #8 color/stencil/z e #16 coverage sample; in realtà i 16 coverage sample rappresentano il totale dei sample ed è un’indicazione che fornisce il livello qualitativo dell’AA. Se guardi, infatti, lo schema a fianco (in caso di 16x) i sample sono in tutto 16 e non 8+16 o 4+16. Nella tabella successiva (dove sono riportati i valori qualitativi corrispondenti in dx10) si vede che al 16x e al 16xQ corrisponde un valore equivalente pari a 16 sample.

Scrivi un commento!

Aggiungi il commento, oppure trackback dal tuo sito.

I commenti inseriti dai lettori di AppuntiDigitali non sono oggetto di moderazione preventiva, ma solo di eventuale filtro antispam. Qualora si ravvisi un contenuto non consono (offensivo o diffamatorio) si prega di contattare l'amministrazione di Appunti Digitali all'indirizzo info@appuntidigitali.it, specificando quale sia il commento in oggetto.