In questo numero analizzeremo il funzionamento di una comune scheda video con accelerazione 3D hardware.

Premessa

Data la complessità di tale argomento mi limiterò ad una descrizione superficiale, per non cadere troppo in tecnicismi, con qualche nota più tecnica man mano che si prosegue in fondo all’articolo. In base ai miei impegni e alla vostra disponibilità (non mi va di scrivere articoli impegnativi, se non interessano a nessuno!), potrei scrivere anche una versione “advanced” dell’articolo, ma in tal caso dovrei spezzarlo in 4-5 parti oppure pubblicarlo come unico file PDF di almeno una decina di pagine…

Dobbiamo introdurre innanzitutto alcuni concetti base della Computer Grafica, cioè la composizione di un’immagine partendo da elementi primitivi, che sono il pixel per la grafica 2D e il poligono per la grafica 3D.

Grafica 2D, il pixel

Come tutti (o quasi) sapranno, le normali immagini bidimensionali sono trattate dal computer come una matrice di pixel, ognuno con un suo colore identificato tramite diversi sistemi di codifica. Potete immaginare i pixel come tasselli di un mosaico: visto da una certa distanza, un mosaico fatto bene è completamente indistinguibile da un affresco, questa illusione ottica è la stessa usata per generare le immagini digitali. Per codificare i colori dei pixel esistono diversi metodi, i due più usati nei sistemi moderni sono il cosiddetto sistema True Color e il sistema Indexed Palette.


Il True Color definisce il colore di un pixel quantificando le 3 componenti cromatiche primarie della luce (RGB, dall’inglese Red Green Blue, cioè Rosso Verde Blu), assegnando cioè dei valori alle singole componenti che, una volta sommate, restituiscono il colore originale. Ad esempio, codificando i colori primari con 8 bit ciascuno ((ma sono diffuse anche codifiche a 4-6 bit per i vecchi giochi, o anche 12-16 bit per la grafica professionale ad alta definizione)), è possibile specificare una gamma di 256 gradazioni (2 elevato 8 ) per ogni componente, per un totale di 256 x 256 x 256 possibili colori (circa 16 milioni). Se vogliamo disegnare un pixel nero basta indicare il valore 0 per ogni componente (0-0-0 in RGB), per il grigio si usano valori uguali di ogni componente (x-x-x in RGB, dove x è un valore qualsiasi da 0 a 255, ad esempio 200-200-200), per il rosso puro si usa 255-0-0 e così via.

Nel sistema Indexed Palette ((in italiano “tavolozza indicizzata”)), esiste una tavolozza, solitamente memorizzata in una memoria speciale dell’hardware video, che contiene un certo numero di colori utilizzabili. Ogni pixel è quindi indicato con un singolo byte, risparmiando quindi una notevole quantità di memoria. Se la palette contiene il verde come primo colore, il rosso come secondo e il bianco come terzo colore, per indicare in successione 3 pixel con i colori della nostra bandiera è sufficiente la sequenza di byte 1-3-2 ((notare che adesso con 3 byte abbiamo indicato 3 pixel, mentre in modalità True Color sarebbero stati necessari 9 byte, 3 per ciascuna componente moltiplicati per il numero di pixel)). Se vogliamo trasformare l’immagine nella bandiera francese, basta modificare il colore #1 sostituendolo con il blu senza modificare realmente l’immagine.

Questo secondo sistema ha avuto notevole gloria in passato per i vantaggi dovuti alla poca memoria necessaria per memorizzare le immagini, per la flessibilità nella creazione di effetti speciali (come l’effetto della bandiera, ma si possono creare facilmente anche delle dissolvenze variando la luminosità di tutti i colori della tavolozza dal nero ai colori originali e viceversa) e per la minore richiesta di calcoli da eseguire (ovviamente avendo meno byte da generare/elaborare, il processore impiega meno tempo). L’altra faccia della medaglia è data dalla scarsa risoluzione cromatica, cioè il basso numero di colori rappresentabili contemporaneamente (tipicamente 4-8-16 ecc… fino ad un massimo di 256, raramente più di 256). Per questo motivo, con l’avanzare della tecnologia, l’abbattimento dei costi delle memorie e l’aumento vertiginoso della potenza elaborativa delle CPU, ci si è orientati verso l’uso massiccio della modalità True Color che offre una resa grafica praticamente realistica.

Grafica 3D, il poligono

Alla base della rappresentazione tridimensionale di un oggetto, vi è una sorta di modellino approssimato, realizzato con una superficie sfaccettata, le cui facce sono generalmente triangoli o quadrilateri. Tralascio i dettagli matematici, potrebbero casomai essere spunto per un argomento avanzato di programmazione, e mi concentro più sull’aspetto pratico.

(Modello 3D di Lamborghini realizzato usando dei quadrilateri come poligoni, immagine tratta da www.3-d-models.com)

Modello 3D di Lamborghini

La costruzione di un’immagine tridimensionale parte da questo modello, su questo vengono “incollate” delle immagini bidimensionali (chiamate texture o skin, in italiano rispettivamente tessuto o pelle) che che possiamo paragonare agli adesivi che si attaccano sui giocattoli e infine, tramite dei complicati calcoli matematici, vengono applicati degli effetti di luce che conferiscono realismo all’immagine, come ombre, riflessioni, diffusioni, rifrazioni, ecc…

Infine i dati passano attraverso delle unità ROP ((Raster OPeration)) che si occupano di disegnare effettivamente i pixel usando le informazioni elaborate negli stadi precedenti.

L’accelerazione hardware 3D

La quantità enorme di calcoli ((per gli addetti ai lavori: si tratta in larga parte di prodotti fra matrici 4×4 per le trasformazioni geometriche, la proiezione prospettica e gli effetti di luce, calcolo di curve di interpolazione lineare o anisotropica per il filtraggio delle texture, molti dei quali eseguiti su numeri a virgola mobile, molto pesanti in termini di risorse di calcolo e di memoria)) necessari ha per lungo tempo limitato le possibilità della grafica tridimensionale, in quanto anche con i più potenti processori oggi in commercio non è possibile ottenere animazioni fluide, realistiche e ad alta risoluzione.

Entrano in campo i cosiddetti acceleratori hardware 3D. Si tratta in sostanza di speciali microprocessori, altamente specializzati per eseguire poche operazioni matematiche ma a grande velocità e su grosse quantità di dati contemporaneamente ((la stessa istruzione viene eseguita simultaneamente su interi “pacchi” di dati)). Questi speciali processori, da ora in poi chiamati GPU ((Graphics Processing Unit)), sono costruiti specificamente per eseguire i calcoli necessari alla generazione delle scene tridimensionali. Per ottimizzare al massimo questo compito, vengono realizzate al loro interno delle “catene di montaggio” chiamate pipeline, che funzionano in modo analogo alle catene di montaggio industriali:

(Schema generico di una pipeline tradizionale)

Pipeline tradizionale, schema generico

La pipeline carica i dati, che contengono le posizioni dei vari poligoni, ed inizia ad effettuare i primi calcoli applicando delle trasformazioni geometriche. Successivamente, questi dati trattati passano allo stadio successivo della pipeline, dove vengono applicate le immagini bidimensionali che formano le texture. In successione si passa allo stadio di filtraggio delle texture, e così via fino allo stadio finale della pipeline che invia il risultato di tutti i calcoli alle unità ROP ((Raster OPeration)), che generano i pixel dell’immagine finale e li caricano nella memoria video, pronta per essere stampata sul display. La cosa sorprendente è che quando il secondo stadio della pipeline elabora i dati in arrivo dal primo stadio, questo a sua volta carica ed elabora dei nuovi dati. Quindi ogni stadio della pipeline, contemporaneamente, sta lavorando su un “pezzo” del flusso di dati e quando termina lo spedisce allo stadio successivo e preleva i nuovi dati dallo stadio precedente, senza interruzioni, proprio come in una efficiente catena di montaggio!

Questo meccanismo è ulteriormente potenziato, grazie alla miniaturizzazione crescente dei circuiti integrati, installando sulla stessa GPU decine di pipeline funzionanti in parallelo. La massiccia ottimizzazione è resa possibile proprio grazie alla natura “monotona” dei calcoli necessari per la grafica 3D che, pur essendo molto complicati, sono sempre gli stessi quindi facilmente ottimizzabili.

Pillole

Le immagini in formato GIF sono codificate secondo il sistema Indexed Palette e, per occupare ancora meno spazio, la tavolozza può avere un numero variabile di colori in modo tale da usare il minor numero possibile di bit per ogni pixel. Il tutto viene poi compresso con un algoritmo simile al famoso Zip. Invece le immagini Bitmap, PNG ((Portable Network Graphics)) e JPEG ((Joint Photographics Expert Group)) codificano i colori secondo il sistema True Color. Per ridurre la memoria occupata usano, rispettivamente, la compressione RLE ((Run-Length Encoding))(usata poco frequentemente), compressione gzip (non identica, ma molto simile alla compressione zip) e compressione a blocchi tramite trasformate di Fourier ((in pratica si scompone l’immagine in caselle quadrate e si crea un modello matematico approssimato di queste caselle. Per ottenere l’immagine originale bisogna calcolare delle funzioni partendo da questi modelli matematici, si ottengono i colori dei pixel in modo approssimativo, poi si uniscono tutti i blocchi e si filtra l’immagine per eliminare le imperfezioni e le discrepanze tra i bordi delle caselle. Per questo motivo le immagini jpeg possono essere estremamente compresse, ma in tal caso presentano dei vistosi artefatti)).

La GPU delle schede nVidia serie 8 non usano più la struttura a pipeline, bensì una nuova architettura basata su unità dette stream processor ((letteralmente “processore di flusso”)), programmabili ((quindi non dedicati ad una operazione specifica, al contrario delle pipeline)), massivamente parallelizzate (addirittura la 8800 Ultra ne contiene 128 funzionanti in parallelo), che garantiscono una ripartizione più bilanciata della potenza di calcolo, per fare in modo che la GPU resti inattiva il meno possibile. Questa nuova architettura rende possibile l’utilizzo della GPU anche per compiti diversi dal rendering delle scene 3D, infatti è possibile utilizzare questa risorsa di calcolo anche per simulazioni fisiche o per calcoli generici su grosse quantità di numeri in virgola mobile.

Il chip G80, nome in codice della GPU delle schede nVidia GeForce 8800, contiene 681 milioni di transistor.

La CPU del mio portatile, un Centrino Pentium-M 740, contiene 140 milioni di transistor.

Aiuto, la CPU del mio portatile è entrata in crisi depressiv… Mannagg….off …accenditi… bru..t..far…abutt… carogna….

4 commenti
  1. Ivan
    Ivan dice:

    Comunque i miei complimenti Antonio, sono ricapitato nel tuo sito dopo anni… e devo molto ai tuoi articoli che mi hanno dato la spinta per continuare a ricercare e a migliorarmi. 🙂

    Rispondi

Lascia un Commento

Vuoi partecipare alla discussione?
Sentitevi liberi di contribuire!

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *