Oscurità proiettate

Le ombre sono una cosa divertente: se non ci fossero, i progettisti di sistemi per il rendering sarebbero felici e contenti.

Purtroppo ci sono, quindi quando un giocatore guarda lo schermo e non le vede, grida “Non ci sono le ombre! Questo gioco è becero sterco!”.

Perchè ogni tanto i giochi non presentano le ombre dei personaggi (o degli edifici) oppure, quando lo fanno, non sono poi bellissime?

Il motivo è semplice: fare le ombre è molto complesso.

Vediamo un’ombra vera:

In questa immagine possiamo notare varie peculiarità: in primo luogo l’ombra non è completamente nera, perché la luce, nell’aria, non viaggia bella tranquilla ma incontra continuamente pulviscolo ed altre belle cose che la riflettono di qua e di là, quindi anche dentro l’ombra.

In più notiamo che l’ombra dell’uomo è molto netta, mentre quelle delle… ehmmm… vabbè, quel che è, sono molto meno nette.

Perchè? Per lo stesso motivo visto prima: la precisione dell’ombra cambia a seconda della distanza del soggetto dall’oggetto su cui viene proiettata: più è distante più i raggi saranno deviati. Da ciò deduciamo che in un luogo senz’aria, le ombre saranno perfette. Così è, infatti, se guardiamo le foto dalle missioni lunari.

Come possiamo fare a simulare tutto questo? Il proiettare raggi che intersecano cose è fuori discussione: si chiama ray-tracing e in tempo reale, al momento non è una cosa semplice. Anzi, diciamo che al momento ce lo scordiamo (anche se Carmack dice di avere qualcosa in mano a riguardo). Esiste un engine di rendering per Quake 3 in raytracing fatto da appassionati, ma purtroppo va un po’ pianino 😀 . Tipo 1 frame ogni 30/40 secondi.

Quindi, siccome il proiettare i raggi è fuori discussione, come facciamo? Dobbiamo inventarci qualcosa che ci risolva il problema.

In più, facendo così, avremmo ombre nettissime ad ogni distanza, a meno di calcolare la deviazione della luce a causa del pulviscolo (si chiama “scattering”). A questo punto però ci sarebbero tanti bei problemi di precisione. Al momento il real time è fuori discussione.

Possiamo, per ora, utilizzare tre differenti soluzioni:

Proiezione Planare

Purtroppo non so se si chiama così, questa tecnica, poiché non è tanto efficace da esser degna un nome. Diciamo che consiste nel proiettare tutti i punti di un modello 3D su un piano, lungo la linea della direzione della luce:

Questo sistema mostra subito il fianco all’hard core gamer: in pratica se c’è un oggetto sul piano, la tecnica non lo vedrà e andrà semplicemente sul piano.

Certo, il piano può essere inclinato, però comunque se c’è un muro su quel piano, l’ombra non ci andrà sopra. Questo sistema può andare bene per i giochi di calcio, dove le ombre dei nostri miliardari preferiti sono proiettate praticamente sempre e solo sul piano di gioco.

Shadow Volumes

Carmack le ha amate. Non è il solo, c’è anche Starbreeze che ama questa tecnica: sia Chronicles of Riddick che The Darkness usano questo sistema.

Vediamo come funziona: per prima cosa supponiamo di avere il nostro modello 3d (tipo un pallone) ed un piano comunque modellato (cioè non una formula matematica, ma proprio un modello 3d a forma di piano). Ci mettiamo su anche un muro. Ora mettiamo una luce in modo che l’ombra cada sia sul piano che sul muro.

Fatto questo, ci sono da fare tre passaggi:

1) Si disegna la mesh, tirando tutti suoi vertici che “non guardano” la luce molto in là. Questo creerà un volume (da qui il nome della tecnica) che noi speriamo intersechi tutti gli oggetti della scena. In questo passaggio diremo all’hardware di disegnare solo i triangoli che guardano in camera (diciamo quelli “davanti” e non quelli “dietro” alla nostra palla)

2) Si fa un’altra bella passata, disegnando quelli “dietro”. Queste passate non vengono fatte sullo schermo, ma su una struttura chiamata “Stencil buffer”. In pratica lo stencil non si becca il colore, ma se qualcuno scrive su un dato pixel, lui somma “1” al valore di quel pixel. Così sappiamo se qualcuno ha scritto lì.

In seguito “aggiungiamo” la prima “passata” allo stencil, mentre “sottraiamo” la seconda; ci rimarrà così nello stencil una pletora di numerelli che rappresentano proprio l’ombra.

Fatto questo, disegnamo un bel quadratone scuro su tutto lo schermo, premurandoci di dire all’hardware di disegnare solo dove lo stencil è diverso da 0. Così facendo disegneremo la nostra ombra perfetta.

Problemi: in primo luogo dobbiamo disegnare l’oggetto tre volte: una volta per farlo vedere normalmente ed altre due per lo stencil. Fortunatamente qui l’hardware ci viene in soccorso: le moderne schede fanno le due passate in un colpo solo.

Però se vogliamo farlo su tutti gli oggetti della scena, dobbiamo farlo con tutti gli oggetti. Se lo facciamo anche al mondo, siamo fritti. Ma non è finita qui: se inizio a proiettare questi volumi in maniera massiccia, rischio di saturare tutta la sezione finale della pipeline, quella che disegna i pixel, perché in pratica devo disegnare una quantità esagerata di pixel (nello stencil) a causa di questi volumi. Quindi abbiamo due colli di bottiglia.

In più ci sono problemi con modelli molto poco densi poligonalmente, oppure con forme allungate (come un parallelepipedo bello allungato).

Questa tecnica è stata usata fondamentalmente solo da Doom3 (e da chi usa il suo motore) e dai giochi Starbreeze, poiché presto si è rivelata inadeguata: oltre ai due colli di bottiglia, presenta enormi difficoltà a fare ombre sfumate sui bordi (la cosa richiederebbe ulteriori passate. C’è una demo ATI che lo fa in 16 passate 😀 ).

Shadow Map

Questa tecnologia è quella che al momento risulta più studiata in assoluto: in genere in tutti i seminari sulla computer grafica sono presenti delle dimostrazioni dei passi avanti compiuti utilizzando questa procedura.

Come mai? In primo luogo la tecnica dello shadow mapping è di base più leggera: richiede solo un rendering in più oltre a quello standard. Richiede però un hardware capace di fare conti per vertice e per pixel. I pixel shader, per intenderci. Qualche anno fa (diciamo il 2000, la prima volta in cui lessi di questa tecnica) questo poteva essere un limite, ma oggi non più.

Il sistema basilare funziona così:

1) Facciamo il rendering della nostra scena.

2) Facciamo il rendering della scena, mettendo la camera dove sta la luce ed angolata nella stessa direzione di questa.

A questo punto confrontiamo gli Z-Buffer dei due rendering: se lo Z-Buffer della luce in un dato punto è minore (o maggiore, a seconda della piattaforma) dello Z del rendering normale, allora quel punto è in ombra.

Spiego velocemente cos’è lo Z-Buffer: è una superficie grande come lo schermo (se lo schermo è 1.024 x 768, allora anche lo Z-Buffer è 1.024 x 768). In questa superficie viene salvato il valore della coordinata Z di uno punto sullo schermo. La coordinata Z è la profondità. Questa superficie serve per fare lo Z-Test: quando disegnamo qualcosa sullo schermo, prima di farlo, controlliamo lo Z-Buffer. Se lo Z che vogliamo scrivere è minore (o maggiore; comunque più “vicino” alla camera) di quello che c’è già scritto, allora vuol dire che il punto che vogliamo scrivere è visibile perchè non c’è niente davanti. Se no, no. Questo ci consente di disegnare gli oggetti nell’ordine che vogliamo, senza che quelli disegnati dopo coprano quelli disegnati prima.

Dicevamo che la tecnica dello shadow mapping consiste fondamentalmente, quindi, nel disegnare dei punti derivati da una elaborazione dello Z-buffer.

Per fare questo, però, dobbiamo disegnare il mondo anche dal punto di vista della luce: operazione che si effettua su di una texture. Ovviamente, più questa texture è grande peggio è. Fortunatamente a noi interessa lo Z-Buffer di quel rendering, quindi possiamo anche disegnare tutti gli oggetti bianchi, senza pixel shader. Quando si fa così, gli hardware moderni fanno fare al rendering una specie di “corsia preferenziale”, saltando un bel po’ di stage nella pipeline, andando velocissimo.

Quali sono i problemi? Ci sono delle angolazioni sfortunate, che danno un sacco di problemi (li notate bene bene in Devil May Cry 4). In più ci sono sempre delle angolazioni cha fanno vedere i pixelloni giganti (lo notate bene sempre in Devil May Cry 4 :D). Nonostante questo, la ricerca continua perchè mediante questa tecnica è possibile fare delle buone ombre sfumate sui bordi (ne vediamo degli esempi in Crysis e GTA4), oltre che, mediante modifiche e moglioramenti, di fare delle buone ombre su tutti gli oggetti in scena.

Ma perchè ancora ad oggi le ombre non sono bellissime come quelle vere? O almeno come quelle nei film di animazione in CG?

Perchè ovviamente anche fare i conti di cui sopra costa. Quando fare le ombre inizia a costare, diciamo 5 millisecondi, allora può darsi che inizi a costare troppo. I rendering per quei film prendono bel più di 5 millisecondi 😀

Al momento il top della tecnologia è Crysis e ci mostra ombre di certo belle, ma con questi difetti:

  • Non è molto diversa la sfumatura tra oggetti lontani ed oggetti vicini
  • Qualche problema di aliasing sugli oggetti lontani
  • Puntini e dithering piuttosto evidenti da vicino
Perchè tutto questo? Perchè altrimenti non ci starebbe dentro con i tempi.
La ricerca prosegue sempre, e se solo confrontiamo le ombre di GTA4 con quelle di Assassin’s Creed notiamo un enorme incremento.
Quanto dovremo aspettare per non vedere più i puntini ed avere delle ombre perfette, magari da più sorgenti di luce e con un diverso grado di sfumatura? Non molto: le ombre sono uno dei campi più studiati della grafica real-time, quindi stimo che entro tre anni il problema dei puntini sarà sparito: credo che un aumento dinamico dei conti che si fanno per farlo possa ridurlo moltissimo, ma per eliminarlo bisognerà pensare in un altro modo, ad esempio un post processing dell’ombra stessa. Tutto questo richiede altro tempo, che al momento non c’è.
Non esiste niente di definitivo, quindi, per quanto riguarda questo argomento. Ma siate fiduciosi 🙂

14 commenti su “Oscurità proiettate

  1. Mi quasi dispiace che i programmatori si sbattano tanto e io puntalmente disattivi le ombre come prima cosa per guadagnare frame.

  2. Comprai una Matrox G400 perchè era una delle poche schede video
    che permetteva l’uso dello Stencil Buffer 😀

    Devo dire che Assassin’s Creed sulle ombre è pressochè impeccabile,
    GTA4 è ancora meglio? Che storia !! .D

  3. Il ray tracing, come tecnica di rendering, esiste da almeno vent’anni 🙂 Non mi stupirei se l’engine usato per fare le cuscene di acquaventura fosse stato in raytracing. Il render off-line in ray tracing è ancora oggi utilizzato, ad esempio c’è un engine chiamato “povray”, che è free e molto potente. Ovviamente non è real-time 🙂

  4. Bellissimo articolo! Grazie! Al prossimo farai le fonti di luce (da quella finta a quella volumetrica inversa? )
    Per Karat: il RT esiste da almeno 20 anni, ma richiede un tempo di calcolo esagerato. I filmati erano precalcolati. Ad esempio quest’immagine di un pod rotante con effetti di luce volumetrica inversa e ombra morbide ha richiesto quasi 4 minuti. http://img386.imageshack.us/img386/6846/katakis2hj5.png
    nei videogiochi possono ottenere risultati simili in real time,ma non identici.

  5. Cherno, a me pare che GTA sia molto peggio di AC, ombre approssimate, con un sacco di artefatti e che producono effetti ben poco next gen quando si applicano ad altri modelli 3D, specie a quelli dei personaggi.

    Probabilmente sono ottimizzazioni per guadagnare velocità e non ci si fa molto caso quando si gioca.

    Io come Nevade spesso disattivo le ombre e altri effetti avanzati non per guadagnare frame ma per ovviare a problemi di game design: ombre e altri artefatti visuali (come il bump mapping molto dettagliato sul terreno) per aumentare il dettaglio della scena spesso aggiungono un sacco di rumore di fondo che rende meno distinguibili dettagli importanti al fine ludico.

    Esempi di questo problema mi vengono in mente con Marvel Ultimate Alliance e con moltissimi MMOG dove i dettagli avanzati impediscono di vedere alcune cose che dovrebbero essere evidenziate meglio se si vuole mantenere il realismo visivo senza ledere la giocabilità.

  6. Questo articolo mi è interessato più dei precedenti che bene o male trattavano tematiche note almeno in superficie.
    Qui invece si è stati più tecnici ma allo stesso tempo chiari e questo l’ho apprezzato.
    Secondo me non ci starebbe male un breve elenco di argomenti e materiali correlati per chi ne vuole sapere di più e magari vuole avvicinarsi in modo più attivo ed eventualmente imparare qualcosa che poi possa utilizzare.

  7. Guarda Matteo, AC è uno dei pochi giochi che riesce ad usare il principio
    delle Shadow Maps senza creare troppe porcate a video. Certo le imprecisioni
    ci sono, ma sono celate bene e soprattutto non infastidiscono.
    Il tutto poi con un peso relativamente leggero, complice anche il fatto che
    la luce solare è fissa e non ci sono altre fonti di illuminazione che generano
    ombre.

    Un altro gioco che mi ha colpito per la qualità dell’illuminazione è STALKER,
    unico difetto di questo è che le mappe d’ombra sono un pò sgranate causa
    risoluzione. D’altro canto però qualsiasi oggetto proietta ombra, anche il
    più insignificante, ed abbiamo anche ombre generate da più punti luce.

    GTA4 non l’ho provato quindi non so quanto sia efficace ed a che livello
    tecnico sia il suo comparto di illuminazione.

    Quel che è certo è che il motore della Crytek ancora non vede rivali .D

  8. Alex, ottimo articolo, come sempre. Hai nominato DMC4, hai fatto bene in quanto il suo motore lo reputo davvero fantastico non fosse per il problema delle ombre, che hai giustamente evidenziato. Non capisco però una cosa, il problema lo si nota MOLTO più all’esterno che all’interno degli edifici (basta anche la demo per notare questa differenza), come mai?

  9. Eccomi qui, dopo tanto tempo ed un sollecito 😀

    Ti spiego: per fare delle belle shadow maps contano tanti parametri: l’orientamento della luce, la sua posizione e la definizione della texture su cui si farà la shadow map.

    Se la luce è lontana, quando si fa il rendering dal punto di vista della luce, beh, è facile che gli oggetti disegnati saranno piccoli, poichè distanti. Poi però la texture va messa su tutto lo schermo ed ecco che TRIC! Abbiamo i pixelloni 😀

    Ci sono molte tecniche per andare contro a questo problema, ma DMC4 non ne usa nessuna 😀 Infatti usa proprio la tecnica base, senza niente.
    Quindi funziona bene in ambiente facilmente controllabili come quelli chiusi, mentre all’aperto, dove la luce è necessariamente più in alto, succedono i casini 😀

    Sulla “posizione” della luce ci sarebbe da discutere, visto che una luce direzionale non ha una posizione, ma credo che il concetto possa essere chiaro così 🙂

Rispondi

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.