L’evoluzione dell’acqua

Oceani, laghi, fiumi, pozzanghere, paludi. Acque con più o meno gradi di purezza. Moti caotici, onde rifrattive, schizzi d’acqua ed animazioni complesse. Per i 3d game programmers la buona reallizzazione di fluidi è un importantissimo passaggio per la riuscita di un motore grafico. La complessità nella rappresentazione di bacini acquosi nasce con l’avvento della 3d graphic: i liquidi sono per definizione mobili e tendono ad occupare tutto lo spazio intorno a loro; oltre ad un problema grafico esiste quindi un problema dinamico, assente nella rappresentazione di terreni. Con questo breve articolo vediamo come gli sviluppatori hanno affrontato e cercato di risolvere questa affascinante sfida coadiuvati dall’evoluzione tecnologica.

Il primo esempio che riporto è Tomb Raider. Nel lontano 1996 l’acqua non era altro che una texture animata “incollata” a mesh piane. Niente di più semplice. La trasparenza era data dall’alpha blending delle texture e l’effetto finale era quello di macchioline bianche che si muovevano più o meno velocemente.



Nel 1997 un grande evento scosse il mondo videoludico: 3dfx produsse la prima scheda grafica 3d capace di apportare un’accelerazione treddì. E’ l’anno di Quake2 che, per il suo motore grafico, supportava le librerie OpenGL e Glide (le famose librerie proprietarie di 3dfx). Al contempo, però, per quanto concerne i fluidi passi avanti non furono registrati: la lava era sempre una texture animata su di un piano immobile.

Nel 2001 si iniziava a vedere qualcosa di nuovo con Splashdown, un giochino di moto d’acqua per Playstation2. Come potete vedere dallo screenshot l’acqua possedeva una certa dinamicità: la scia della nostra moto generava delle onde rappresentate da una reale modificazione della mesh.

Nel 2002 arrivava negli scaffali Neverwinter Nights supportato dall’Aurora engine. Questo motore grafico era uno dei primi a far uso dei pixel/vertex shader e verrà impiegato anche in Star Wars: Knight of the Old Republic ed il suo sequel. Grazie a effetti “per-pixel” i programmatori poterono far uso di tecniche quali bump mapping, specular highlights, alpha blending ed altri simpatici effetti.



Parlando di acqua, come si fa a non citare Far Cry? Impossibile. Nel tempo il motore grafico CryEngine, inizialmente compatibile con le directx8, subì vari upgrade e nelle sue ultime incarnazioni faceva uso della tecnologia HDRI – grazie al supporto delle directx9 e quindi dei pixel shader 2.0.  Nello screenshot è possibile notare l’utilizzo dell’effetto Fresnel: l’acqua più vicina ci appare trasparente mentre quella lontana riflette l’ambiente circostante. Nello stesso periodo usciva Half-Life 2 che, con il suo source engine, ci regalava una splendida realizzazione di pozzanghere, fiumi e mari. Anche nel source engine l’acqua possiede il sopracitato fresnel effect.





La Lionhead diede alla luce nel 2005 Black and White 2. In questo progetto collaborava Fek, un nostro conpatriota che si occupava tra le altre cose dell’acqua. Notevole l’effetto, sia da una inquadratura ravvicinanta che da molto lontano.

Nel 2006 la critica venne positivamente scossa dagli splendidi paesaggi di Oblivion. Le immense colline riflesse nei suggestivi corsi d’acqua ed un oculato uso dell’HDRI creano quella calda atmosfera che chiunque abbia giocato ad Elder Scroll IV conosce. Il motore grafico sotto il cofano era il Gamebryo, un 3d engine cross platform utilizzato in molti AAA games.



Ci avviciniamo ai giorni nostri con un 2007 che ci ha regalato l’Unreal Engine 3, un motore grafico molto versatile e di grande impatto visivo. Vengono sviluppati con questo engine importanti titoli come Unreal Tournament III, Bioshock, Gears of Wars e molti altri, contemplando interessantissimi effetti particellari.

Ed arriviamo infine all’attuale stato dell’arte con, neanche a dirlo, Crysis es il suo Crytek engine. Gli screenshot che trovate qui sotto sono tutti ad impostazioni Very High e quindi in DirectX 10 + Pixel Shader 4. E’ proprio il caso di dirlo, dal primo Tomb Raider ad oggi di acqua sotto i ponti ne è passata un bel po’ (argh)!



Cosa ci riserva il futuro? Ciò che a noi oggi sembra “fotorealismo” tra qualche anno sarà già superato. Chiudiamo questo approfondimento con alcuni screenshot “mozzafiato” di Alan Wake, prossimo titolo full directx10 sviluppato da Remedy.

Programmare bene

Da quando è uscito Crysis (ma anche da prima) continuo a leggere questa frase:

Crysis è programmato male perchè sul mio uber-pc scatta con tutto al massimo“.

Cosa possiamo dire di Crysis? Probabilmente che le stime di crescita della potenza dei PC sono state troppo ottimistiche.

Possiamo dire che sia stato programmato male? No. Perchè no? Perchè programmare bene non vuol dire programmare in modo che il gioco sia veloce. Quello è solo un punto, probabilmente nemmeno il più importante.

Vediamo cos’altro è importante. Un gioco è ben programmato se segue le regole della buona programmazione che valgono per ogni software:

Codice documentato;

– Accoppiamento tra i moduli al minimo possibile;

Sviluppo il più possibile Data-Driven;

Chiarezza;

Solidità;

Ottimizzazione.

Prima si affronta il design, poi si scrive il codice nella maniera migliore possibile in modo che rispetti le richieste e infine, se il collo di bottiglia si trova nei nostri listati, si procede con l’ottimizzazione.

Consideriamo in dettaglio tutti i punti.

CODICE COMMENTATO

Se il codice non è commentato e la documentazione non viene scritta, qualora il suo autore dovesse abbandonare l’azienda, con lui andrà perso anche il suo know-how. Questo non deve succedere, perché una qualunque modifica al software nella parte di sua competenza sarebbe estremamente complessa e di certo genererebbe grossi bug di arduo tracciamento. Il codice va dunque commentato e la documentazione redatta. Crysis soddisfa questo punto? Siccome l’engine viene venduto, possiamo desumere che venga venduto con documentazione annessa. In passato ho lavorato con Renderware e tutto era documentato, sia nel codice sia nella documentazione allegata. Non vedo perchè Crysis avrebbe dovuto toppare su questo punto, ma siccome non possiamo saperlo, lasciamolo lì dov’è.

ACCOPPIAMENTO TRA I MODULI AL MINIMO POSSIBILE

Supponiamo che la sezione dell’input ad un certo punto voglia usare un pezzo del gioco, che gestisce magari il suono delle collisioni tra due oggetti.

E’ così creato un accoppiamento tra due moduli. Ciò può portare a mille problemi: ad esempio se modifico la collisione, di colpo l’input potrebbe non funzionare più. Per tale ragione si cerca di tenere gli accoppiamenti al minimo, limitandoli a ciò che è logicamente collegato ed ai tipi base.

Un esempio estremo: se ho un dato condiviso da più moduli e uno di questi lo modifica, magari il programmatore nemmeno immagina che questo viene utilizzato da qualcos’altro, quindi questo qualcos’altro non funzionerà più. Errori del genere portano via giorni. Crysis è a posto o ha tanti accoppiamenti? Se leggiamo le feature, notiamo che non può essere che con pochi accoppiamenti: una tale struttura permette un fortissimo riutilizzo dei componenti (giacché vivono in maniera autonoma). Già la sola integrazione perfetta con un ambiente di authoring ci fa capire che i moduli sono distinti.

SVILUPPO IL PIU’ POSSIBILE DATA-DRIVEN

Ed è qui che i fanatici dell’ottimizzazione gridano: una gestione data driven è più lenta di una gestione code-driven. Questo perché il dato va letto, interpretato e gestito, mentre se piazzato direttamente nel codice, questo è già pronto quando il gioco si compila.

Ad esempio: di che colore vogliamo le scritte sullo schermo? Se mettiamo il colore nel codice, questo sarà nell’eseguibile, pronto ad essere assegnato quando richiesto. Se lo mettiamo in un XML, questo andrà letto e interpretato, per poi prendere il dato e metterlo nella variabile dopo, magari, una conversione di tipo.

Quindi, perchè si fa? In primo luogo perché se la lettura del file si realizza in maniera oculata (ad esempio con un parser SAX invece che DOM per l’XML, oppure con un parsing in memoria per un binario), allora allungherà i tempi di startup di un tempo risibile, e inoltre in secondo luogo renderà il gioco immensamente più modificabile e tunabile per i designer ed i grafici (oltre che per l’utente). Pensiamo solo alle mesh: cosa succederebbe se il programmatore mettesse tutte le posizioni dei vertici nei sorgenti? Succederebbe che se al grafico una mesh non piace, bisognerebbe cambiare il dato a mano e ricompilare; ovviamente non ha senso: ha molto più senso che il grafico modifichi la mesh incriminata in 3dStudio Max, la riesporti e la ricarichi in gioco. Oppure pensiamo ad un designer che voglia inserire i nomi dei giocatori in un titolo calcistico, o ad un programmatore che intenda scrivere un nuovo shader.

Insomma, i benefici nei tempi di sviluppo sono talmente grandi che le perdite in fase di inizializzazione vengono del tutto riassorbite. Se consideriamo che il concetto di gioco data-driven risultava già ben presente ai tempi del C64, possiamo facilmente notare quanto sia importante.

Crysis è provvisto di tale approccio? In maniera massiccia: abbiamo editor per gli effetti, editor per gli stati, editor per i menù, editor per il gioco, editor per l’AI, editor per l’audio, editor per tutto 😀 Non c’è niente di hardcodato, tutto è data driven, per la massima modificabilità senza dover ricompilare alcunché. Questo ne conferma anche la modularità: il fatto che possiamo mettere vari moduli per creare degli effetti ci fa intuire che essi siano ben distinti e non connessi tra loro.

CHIAREZZA

Quando si scrive un programma, lo si deve fare pensando che saranno degli occhi umani a leggerlo. Il compilatore non ha molto interesse nella chiarezza: lui prende tutto quello che la grammatica del linguaggio accetta.

Se iniziamo a indentare il codice a caso e a dare alle variabili nomi inconsistenti (come ad esempio “deltaT” a variabili che indicano il tempo assoluto), allora andremo incontro a sessioni di debug molto faticose. Parimenti, se abusiamo del preprocessore dovremo affrontare simili avversità.

Crysis soddisfa questo requisito? Boh, spero che i lead controllino il codice, ma immagino di sì 😀

SOLIDITA’

Un software è solido quando, di fronte a tutti gli usi previsti dall’interfaccia d’uso, dagli input e dagli output, rimane funzionante e operativo nei tempi richiesti. Se di fronte ad una sequenza di input considerata corretta, il software entra in deadlock o crasha, allora non può essere ritenuto solido.

La solidità viene valutata con test mirati a stressare il sistema, come ad esempio saturare l’input, oppure lasciare il gioco a girare per giorni e giorni.

Come si ottiene la stabilità? In primo luogo con la disciplina: tutte le variabili allocate vanno prima o poi (quando serve) disallocate. Tutte le risorse hardware vanno rilasciate quando non servono più e tutto il sistema deve pensare di avere una serie di check per valutare che queste condizioni siano rispettate. In genere un gioco stabile è un gioco programmato con attenzione, come tutti i software e comunque per qualunque opera di ingegneria. Un ponte non crolla se è stato progettato con attenzione, giusto?

Quando, d’altro canto un software è instabile? Quando di fronte ad una precisa sequenza di operazioni considerate “safe” il programma inaspettatamente si blocca (nel caso in cui un software funzioni in multithreading, questa sequenza potrebbe non essere sempre riproducibile con facilità, rendendo il debug un autentico bagno di sangue).

Per evitare tali eventualità, si cerca di tenere il codice il più semplice possibile, tralasciando voli pindarici o ottimizzazioni spinte sulla macchina (tanto quelle ottimizzazioni il compilatore le sa fare meglio di noi, quindi perché preoccuparci?).

In Crysis è così? Non possiamo saperlo. Ma il gioco è stabile? Per quanto ho visto, funziona su una pletora di configurazioni senza crashare per molte ore di fila. Un miracolo, su PC.

OTTIMIZZAZIONE

Quando si trova un collo di bottiglia, si cerca di eliminarlo ottimizzando. Già in passato abbiamo visto che l’ottimizzazione sull’assembly senza cambiare algoritmo porta a guadagni tanto risibili da non avere senso.

Sì, amighisti, sì, lo so che sul vostro Amiga girava Lionhead: anche lì non pensiate che l’ottimizzazione sia stata fondamentalmente sulla macchina, bensì è stata effettuata su algoritmi custom e appositamente sviluppati per l’uso richiesto. Sono quelle le cose che consentono di ottimizzare tanto e davvero.

Vediamo: se c’è un collo di bottiglia sul processing dei pixel shader che si fa? Dove si controlla: nei conti degli shader o nei campionamenti delle texture? Se nei campionamenti, la scelta giusta consiste nell’ottimizzare le dimensioni delle texture: texture piccole per la roba lontana o piccola. Se è nei vertex shader, stessa cosa: sono i conti o il fatto che le mesh hanno una barca di vertici? E così via, per tutti i reparti del gioco.

Per Crysis, proviamo a pensarci: dov’è il collo di bottiglia? Ovviamente sui dati: si vuole mostrare sullo schermo TROPPO. Se vi fosse stata la necessità di andare più veloci, al fine di rendere l’insieme più gestibile, allora si sarebbe proceduto ad una scrematura, adoperando mesh meno dense e così via. Non può essere altro: il solo fatto che tutta quella roba SI MUOVA e sia giocabile in tempo reale ci fa capire che è stato fatto tutto nel modo migliore.

E la faccenda dei multicore? Beh, la solita fregnaccia da redattore (anche se in questo caso è peggio: da redattore esperto di hardware). Ne parliamo prossimamente, ok?

CONCLUSIONI

In definitiva che possiamo dire? Possiamo sostenere che Crysis sia programmato male? No, perché quello che si vede è fatto in maniera eccezionale, mentre quello che non si vede non lo possiamo sapere.

E ora via col flame!

Alta dinamica per le nostre retine

A chi tocca oggi? All’HDR, direi.

L’HDR è stato per lungo tempo una specie di mito: la diatriba tra “HDR vero” ed “HDR falso” mi ha divertito a lungo. Ovviamente il tutto era portato avanti dalle riviste, che purtroppo parlano a vanvera di quello che non sanno. Non si distaccano minimamente dalla stampa generalista che tanto scherniscono, ma vabbè.

Vediamo un po’ cos’è questo HDR. In primo luogo “HDR” è l’acronimo di

High Dynamic Range

Eh? Ma che vuol dire? Non sembra nemmeno una tecnica, ma una definizione. E’ proprio questo infatti. Dire che un gioco “Ha l’HDR” non ha molto senso, così come dire “l’HDR è un effetto”. Vediamo perchè.

Noi sappiamo che il nostro amato e stimato monitor ci può far vedere milioni di colori. Quanti, esattamente?

Prima di rispondere, credo sia sensato spiegarvi come funziona il nostro bulbo oculare (a me ha sempre fatto ridere la parola “bulbo”, a voi no? 😀 ).

Il nostro amatissimo ha sul fondo una roba chiamata “retina”. Sulla retina abbiamo due tipi di recettori: i bastoncelli ed i coni. I primi sono sensibili alla Luminanza, ossia ci dicono quanto forte è la luce.

I secondi sono invece sensibili al colore. I coni sono divisi in tre gruppi, quelli sensibili alle radiazioni basse, medie ed alte. Per essere più chiari, sono sensibili al rosso, al verde ed al blu. Questi recettori sono tutti sul fondo della retina, tranne dove c’è il nervo ottico (dove c’è una cosa non può essercene un’altra): è lì che c’è la famosa “zona cieca”.

Da qui capiamo finalmente perchè tutto il mondo della grafica gira attorno alla triade (o tristimolo) RGB: perchè il nostro occhio è fatto così.

Dicevamo prima: quanti colori possiamo rappresentare con il sistema RGB dei computer? Un sistema moderno ha 8 bit per ogni componente, quindi rappresenta numeri da 0 a 255. Lo 0 significa “niente colore”, mentre il 255 significa “colore a piena potenza”.

Se mettiamo i tre colori in fila, otteniamo un numero da 24 bit. A questo punto è facile: 2 elevato alla 24 è il numero di colori.

Quindi: 16.777.216

Tanti, vero? L’occhio ne vede circa 16 milioni, pensate un po’: quindi meno di quelli rappresentabili. Il che non significa che il monitor visualizza più colori di quelli che vediamo, ma ne parleremo un’altra volta.

Ok, torniamo all’HDR: dicevamo che se diamo 8 bit, abbiamo un range da 0 a 255 per componente. Questo range, che notiamo essere in numeri interi, viene convertito per fare i nostri conti in un range che varia da 0 ad 1, dove si lavora con numeri con la virgola (tipo 0.5, 0.8 e così via).

E se noi dessimo un range molto più ampio per componente? Tipo 10 o 32 bit ognuno? Potremmo avere un numero di tipo “float” (quindi con la virgola) che potrebbe andare su tutto il range dei float, quindi, chessò potrei scriverci dentro 100, oppure 1.000,6 oppure anche 1.000.000 .

Ecco, questo è l’HDR: avere i componenti del colore con range ampio, non tra 0 ed 1, ma che possa assumere valori molto più alti (o bassi).

Capiamo subito che non è un effetto in sè: è una specie di proprietà.

Quindi HDR non significa “il bagliore quando guardo il sole” o “quando esco dalla canverna sono accecato” o “al buio vedo fondamentalmente il rosso”: tutti questi sono effetti possibile grazie al fatto che stiamo facendo il rendering su superfici HDR (ossia con componenti RGB belle grosse), ma l’HDR è la proprietà della superficie, non l’effetto.

Detto questo, cerchiamo di capire perchè si è ritenuto necessario fare i conti in alta dinamica.

Nella realtà abbiamo luci estremamente forti: il sole, ad esempio, è una luce dannatamente intensa. Senza andare a prendere il sommo imperatore, però, possiamo limitarci ai suoi riflessi: quelli sul mare, ad esempio.

Queste luci sono intensissime ed è impossibile rappresentarle adeguatamente con un range che va solo da 0 ad 1: dovremmo perdere tantissima precisione. Per “tantissima” non intendo “da 0 a 2” ma circa 10 elevato alla 4 😀 (se parliamo di candele, l’unità di misura dell’intensità della luce)

Quindi significa che con l’HDR il nostro monitor emetterà una luce intensa come quella vera? Certo che no, purtroppo (o per fortuna): alla fine di tutto, la nostra immagine dovrà finire su una superficie normale, in modo che l’hardware della scheda grafica possa prendere tale superficie e metterla sullo schermo.

Ma quindi? A che serve l’HDR? A niente? Detto così parrebbe di sì: se non si fa niente, l’immagine in alta dinamica viene semplicemente portata su quella a bassa per essere messa su schermo. Certo, tutti i valori maggiori di 1 verrebbero portati ad 1, creando una immagine inquietantemente sovraesposta.

E quindi? Ecco qui perchè “l’HDR” non è un effetto: di per sè non fa molto. Avendo però la superficie ad alta dinamica, possiamo fare tutta una serie di conti che non potremmo fare con una immagine a bassa dinamica. In nostro scopo è imitare il funzionamento della retina (o di una macchina fotografica, secondo quello che vogliamo fare), quindi per farlo abbiamo bisogno di una scena che abbia le luminanze belle alte, come nella realtà. Alla fine dei nostri conti, avremo una immagine in bassa dinamica, che potremo copiare nella memoria che andrà sullo schermo.

Ma che conti si fanno? Si possono fare dei conti per riprodurre l’abbagliamento dovuto al passare da una zona buia ad una zona chiara. Un’altro conto che possiamo fare serve a dare una colorazione differente alla scena, giacchè il nostro occhio si comporta diversamente a seconda della “quantità” di luce presente.

Il nostro occhio funziona diversamente a seconda della luce presente: ci sono fondamentalmente tre “funzionamenti” principali:

Visione Fotopica: E’ la condizione standard, diciamo una giornata luminosa e allora, con le tipe che prendono il sole al parco ostentando le loro carni.

Visione Scotopica: In questo caso, invece, la luce è molto bassa. Diciamo come quando tutta la stanza è buia e non filtra quasi niente dalle tapparelle ed è notte. Dopo qualche minuto (circa 10) il nostro occhio si abitua e ci farà vedere qualcosa. In questo caso i colori che vedremo maggiormente saranno quelli caldi (tipo il rosso).

Visione Mesopica: Una media tra i due casi precedenti. Diciamo che a questo livello riusciamo ancora a distinguere i colori.

Questi tipi di “visione” possono essere simulati solamente tramite conti su superfici in HDR.

So già che mi verrà posta questa domanda: perchè alcune schede non consentono l’Antialiasing e l’HDR assieme? La risposta è semplice: basta pensare a come funziona l’antialiasing.

In genere funziona così: si disegna la scena su una superficie molto più grande, per poi riscalarla su quella che andrà visualizzata (quindi 1024×768 o quello che preferite). Il rescale, giacchè viene fatto tramite media tra i vari pixel, nasconderà le brusche transizioni di colore, che generano l’aliasing. Siccome abbiamo visto che in HDR si fa il rendering da un’altra parte e non sulla superficie di rendering, capiamo subito che la cosa o la si gestisce apposta oppure niente antialiasing.

Per lungo tempo ho riflettuto se fosse necessario mettere delle formule: ho deciso che qui non ne metterò, ma il prossimo articolo ne sarà profuso. Ovviamente per il vostro sollazzo 😀

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 🙂

Ottimizzazione: Che ne è? Eh?

Eh sì.

Quante volte ho letto “Quel gioco non è ottimizzato!” o “Quel gioco non è ottimizzato!” oppure ancora “Quel gioco non è ottimizzato!”.

In genere mi irrito. Altre volte mi inquieto mentre altre mi pongo domande. Comunque molto spesso mi irrito.

Ma perchè, dopo tutto? E’ così bello discutere con la gente! Quindi proviamo a capire cosa è cambiato nell’ottimizzazione, così magari in futuro avremo le idee più chiare. Da una mente chiara ne deriva una buona digestione e una duratura erezione, quindi partiamo.

La leggenda vuole che nel passato si ottimizzasse l’assembly fino a consumarsi le cornee sui forsfori verdi dei monitor di quei bei tempi che furono.

Ah, quanta verità! Non vi è nulla di più vero! Pensate che talune volte bisognava programmare su un computer e lanciare il gioco su un altro, poichè non c’era memoria per contenere gioco e programma per scriverlo.

Tempi bui, nei quali si scriveva il codice macchina direttamente nelle locazioni di memoria.

Tempi grami, in cui dire “ho 10Kb liberi” significava dire che tutta la memoria di sistema era libera.

Ai tempi era necessario ottimizzare spazio e codice, in modo da far stare tutto in 64K (ad esempio). Quindi si scriveva in assembly, si usavano array fissi, si gestivano immagini a 16 colori e si facevano muovere sprite da 16×16 pixel.

Forse sono andato troppo indietro, ma veniamo ad oggi.

Ad oggi fare queste ottimizzazioni non porterebbe ad un risultato buono. Vediamo perchè.

Supponiamo di avere un computer che fa 10 operazioni al secondo. Chessò, una PS3…. oh no! Ho violato un NDA! Vabbè, dicevo: 10 operazioni al secondo.

Abbiamo un algoritmo che in 5 operazioni è fatto e viene chiamato una volta al secondo. Lo ottimizziamo fino a che non fa ciò che deve in 2 operazioni, miracolosamente senza intaccare la memoria, ma funziona solo su quel tipo di dato e con un numero di elementi fissi.

Uella, un incremento pazzesco! Abbiamo 8 operazioni libere invece che 5.

Ora supponiamo di far girare l’algoritmo da 5 su una macchina che fa 1.000.000.000.000 di operazioni al secondo.

Capiamo da soli che a questo punto, forse è meglio quello da 5 rispetto a quello da 2 poichè è più completo: potremo magari usarlo in più luoghi del codice, senza intaccare le performance.

Ad oggi l’ottimizzazione quindi non può andare sulle minuzie: con le minuzie non ci si mangia via nemmeno un millisecondo.

Bisogna andare più ad alto livello, poichè anche i dati da gestire sono diventati mostruosi.

Quindi i famosi discorsi “Eeeh, ai tempi sì che si ottimizzava, oggi i programmatori pensano solo a godersi i miliardi che guadagnano a colpi di Veline e modelle Victoria’s Secret” purtroppo non hanno senso. Non tanto per la faccenda di Victoria’s Secret (ormai sono anche un po’ stufo di farmi Adriana Lima), ma perchè quel tipo di ottimizzazioni ad oggi sarebbero del tutto inutili.

Quindi cosa è utile? In assoluto, ad oggi, sono fondamentali le strutture dati scelte, il multithreading che blocchi il meno possibile i vari Core, il numero delle draw call e l’ottimizzazione dei dati.

Eh sì, dei dati. Caricare un livello che pesa 500MB o uno che ne pesa 100 ma ha un “look and feel” identico ovviamente cambia un tantino 😀

E qui finalmente accantoniamo il dannato programmatore e andiamo dai grafici. Se i programmatori, con dieci giorni di lavoro, possono tagliare via 1 o 2 millisecondi per frame, beh, i grafici nello stesso tempo sono in grado di tagliarne tipo 7 o 8 😀

Non male, vero? Quindi l’ottimizzazione dei dati è assolutamente fondamentale: decide se un gioco scatta in un dato punto del livello o meno.

Ma come possono fare i grafici a testare il tutto e tunare il livello? Con i tools. E chi li fa?

Il programmatore. E che palle. Sempre in mezzo.

Quindi, arrivati alla conclusione, cosa possiamo dire? Di certo che i programmatori passano la maggior parte del tempo a fare tools che producono dati ottimizzati, poichè è lì che si risparmia il grosso del tempo.

Quindi i tempi delle ottimizzazioni “una istruzione assembly in meno” sono finiti, da un bel po’.

Certo che però quelli erano bei tempi.

Cià vi saluto che c’è Persona 3 che mi aspetta: chissà che oggi quell’emo sfigato del mio personaggio non convinca qualche tipa ad accoppiarsi con lui.

Il ritorno di Dragon Quest

Con l’imminente arrivo della riedizione di Dragon Quest IV per Nintendo DS, cercherò di fare una breve panoramica su questa meravigliosa serie di RPG nipponici che, seppure quasi sconosciuta in Europa, rimane una delle epopee più popolari di sempre e che vanta di un’enorme seguito anche in USA, nonostante i fan siano rimasti a secco per l’intero e florido periodo SNES per le ben note peripezie con il management che Enix ebbe alla fine degli anni 90.

dragon-quest-viii-journey-of-the-cursed-king-20051122112003856

Nato come la risposta nipponica ad Ultima, Dragon Quest ha creato il genere JRPG. Bisogna dire che, nonostante la natura pioneristica del genere, ciò che colpisce è la coerenza nel design che sin dai primi capitoli è stato un aspetto che ha contraddistinto Dragon Quest rispetto ai suoi diretti competitoriimitatori come Final Fantasy. I primi episodi di Dragon Quest mantengono una semplicità ed una chiarezza eccezionale. Anche attività piuttosto banali che titoli contemporanei veicolavano con grossolanità e pressapochismo, come la semplice procedura di esplorazione del mondo, sono veicolati in modo molto naturale: ad ogni barriera geografica (in particolare ai ponti), corrisponde un relativo incremento della difficoltà dei nemici. Il layout stesso del mondo prevede quasi sempre una progressione crescente degli incontri, in qualsiasi fase della storia si sia. Il sistema di incontri, quindi, oltre a fornire un’esperienza progressiva, diventa anche un implicito indicatore della correttezza del percorso scelto. Il sistema di combattimento prevede di recuperare in maniera piuttosto semplice accidentali sconfinamenti in zone non alla portata del giocatore, grazie ad un sistema di ritirata che semplicemente funziona ed alla presenza di item di supporto a prezzi modici che possono essere utilizzati (anzi, devono essere utilizzati) sin dall’inizio del gioco. Chiunque abbia “apprezzato” la distribuzione più o meno randomica degli incontri e dei luoghi nei primi Final Fantasy e abbia ancora i sudori freddi ricordando la martellante quanto inesorabile frequenza degli incontri casuali, apprezzerà la differenza. Anche la difficoltà dei combattimenti ha una progressione molto organica: i personaggi hanno molte difficoltà in fase iniziale ma la progressione della difficoltà non è lineare. Gli incontri di difficoltà crescente non diventano estremamente difficili e non mirano a mantenere costante il livello di sfida ma propongono un modello più verosimile di progressione che aumenti l’autonomia del party e la gestibilità degli incontri da endgame rendendo le cose via via più semplici e gestibili. In parole povere non dovrete mai fare stock di 99 pozioni ogni volta che ci si avventuri fuori da una città nel midend game e si viene sconfitti dai boss per lo più per errori di natura strategica nella gestione del combattimento, piuttosto che per la potenza devastate dei singoli attacchi avversari.

quest2 Bisogna fare anche un inciso sullo stile di gioco di Dragon Quest. Benché esso abbia concretizzato alcuni paradigmi tipici dei JRPG, le meccaniche e l’approccio al gioco sono stati, almeno nei suoi capitoli iniziali, fortemente ispirati agli RPG esplorativi a turni occidentali, come Ultima, Wizardry, Might & Magic e Magic Candle. Nonostante ciò, Dragon Quest è riuscito sin da subito ad omogeneizzare gli elementi di design presenti nei titoli occidentali che, seppure molto ben strutturati ed innovativi per quei tempi, soffrivano di dispersività, scarsa integrazione tra i diversi sotto-sistemi di gioco e di una pessima presentazione generale. Non accadrà mai che i combattimenti dentro e fuori i dungeon siano implementati in modo del tutto diverso (come accadeva in Ultima), che zone adiacenti abbiano mostri di difficoltà profondamente diversa (pick you early CJRPG!) o che esistano una pletora di comandi, icone o shortcut da conoscere a memoria per compiere anche azioni piuttosto semplici. Dragon Quest rispondeva a questi requisiti con un sistema di combattimento semplice ed immediato e con un sistema a menù molto intuitivo e del tutto uniforme sia nelle fasi gestionali che in quelle di scontro. Nonostante le limitazioni intrinseche nel sistema di controllo basato sul joypad a due pulsanti, lo stile dell’interfaccia utente menu-driven di Dragon Quest rimane ancora oggi il punto di riferimento degli RPG per console. Bisogna aggiungere che negli episodi più recenti, Dragon Quest è stato anche uno dei primi RPG a ridurre al minimo la presenza di informazioni a schermo mentre si gioca, aumentando di molto ergonomia ed immersività. Va fatto inoltre notare che all’epoca il gioco era uno dei pochi ad avere un creativo di riferimento (Akira Toryiama) che curasse certosinamente sia gli aspetti visuali che narrativi della serie. La presenza di Toriyama, che negli anni ’80 e ’90 valse a Dragon Quest una presenza praticamente costante in qualsiasi contesto di intrattenimento, si rivelò strumentale per il sucesso della serie che, secondo Famitsu, ad oggi è la proprietà intellettuale rpgistica col più alto numero di copie vendute al mondo.

Come altri titoli giapponesi, anche Dragon Quest ha avuto un cammino evolutivo graduale e solo parzialmente innovativo: nel corso degli anni il sistema ed il design di fondo sono variati di poco, a volte con corsi e ricorsi in termini di meccanismi di gioco (alcuni episodi sono class based, altri sono skill based, etc…). Se la storyline di Dragon Quest vanta due trilogie e due capitoli stand-alone, i miti ed i luoghi della saga sono condivisi ed il sistema di gioco prevede lievi variazioni che sono per lo più funzionali alla narrazione della storia (esaltando ad esempio il semplice protagonista piuttosto che il gruppo), esattamente come accade in Final Fantasy. Quello che rimane è un solidissimo prodotto, anche a distanza di decenni, che ancora si presenta piuttosto bene grazie all’omogeneità che permea tutta la serie. Questo non toglie che chi detesta i JRPG detesterà probabilmente anche Dragon Quest e che chi è votato al culto della Fantasia Finale non accetterà reliquie apocrife nella sua fede, ma c’è da dire che la sua estrema cura nel non indispettire più del dovuto il giocatore con incontri superflui o con necessità continue di farming renderà l’esperienza piuttosto piacevole anche ai Final Fantasy-addicted, magari suscitandogli qualche dubbio circa l’effettiva validità qualitativa della serie nel suo complesso.

La prima trilogia di Dragon Quest ha avuto un successo enorme anche negli Stati Uniti (dove uscì come Dragon Warrior), vantando tra le altre cose un motore grafico interamente revisionato che prendeva di molto le distanze dalla versione nipponica, totalmente priva di animazioni e con grafica più stilizzata (ad una prima analisi sembra un porting di Ultima per console). Per noi Europei, l’unica release degna di nota è stata la non più tanto recente versione per Gameboy Color, uscita in due volumi: Dragon Quest I & II e Dragon Quest III. Se il primo episodio rimane un titolo pioneristico, il secondo ed il terzo episodio sono dei veri e propri colossal: intrecci magistrali coadiuvati da intermezzi animati realizzati con il motore di gioco e personaggi memorabili dettero un valore quasi iconografico a Dragon Quest, valore che la stessa Square riuscì ad elaborare a modo suo solo dopo parecchi anni.

dq9

Oggi Square-Enix ha deciso, molto intelligentemente, di portare su DS solo la seconda trilogia di Dragon Quest, colloquialmente identificata come la trilogia della cittadella volante (anche se i legami tra i singoli episodi sono meno netti dei primi tre capitoli della serie), la meno nota e l’unica che vanta due capitoli (per SNES e successivamente PS1 e PS2) che non hanno mai lasciato il suolo nipponico. La trilogia della cittadella volante, infatti, fu originariamente prevista per il mercato USA ma solo il primo episodio (il quarto della serie, l’ultimo uscito per NES) fu localizzato grazie al management di Enix che non seppe prevedere per tempo l’enorme mole di lavoro di localizzazione necessario, un problema che negli anni a venire fu comune a gran parte della produzione RPGistica nipponica. Poiché all’epoca nessuno studio aveva vere e proprie strutture di localizzazione (che di solito era effettuata alla meno peggio dallo staff di sviluppo), dopo numerose traversie e versioni dalla qualità inaccettabile, Enix decise di rinunciare e di confinare Dragon Quest in Giappone sino a data da destinarsi: solo con il settimo episodio (per Playstation) Dragon Quest avrebbe rivisto il suolo americano (ma non ancora quello europeo). Nonostante la mia scarsissima conoscenza del giapponese, la trilogia della cittadella volante rimane la più solida tra gli story arc dragonquestiani, forse oscurata (ma è questione di gusti) solo dagli splendidi one-shot 7 ed 8 che però arrivarono in un periodo di ulteriore maturità dello scenario RPGistico giapponese.

Tecnologicamente, Dragon Quest IV DS (e i suoi già annunciati seguiti come anche il nuovo nono episodio) sarà completamente aggiornato ed al passo con i tempi, esattamente come accadde con Final Fantasy III: su un motore grafico in full-3D si innestaranno i vecchi sistemi di gioco ed una storyline riscritta senza stravolgimenti, partendo dagli script originali. Se ha funzionato per lo spoglio e discontinuo Final Fantasy III (insieme al II uno dei peggiori capitoli della saga), c’è da credere che, con la trilogia della cittadella volante, il capolavoro sia assicurato. In parallelo alla vecchia trilogia, Square-Enix rilascerà anche il nono episodio in esclusiva per Nintendo DS: il motore grafico sarà lo stesso ma il sistema di gioco è stato pesantemente rivisto introducento parecchie innovazioni sul fronte del gameplay (ancora da confermare ufficialmente) ed integrando parte delle meccaniche previste negli spin-off Dragon Quest: Monsters.

In concusione, Dragon Quest rimane una delle vecchie serie meno conosciute ma forse più accessibili agli appasionati europei: risentendo pochissimo del peso dell’età e fornendo un’esperienza molto più organica dei suoi contemporanei, rimane una delle proprietà intellettuali più interessanti da veder sbarcare sulla corrente generazione di console e forse l’unico titolo JRPG per cui può valere la pena investire nell’acquisto di remake o degli episodi originali.

Le Specie Videoludiche – Parte 3

Ed eccoci all’ultima puntata del bestiario videoludico, ovvero il videogiocatore e il suo essersi diviso in diverse specie nel corso degli anni. Cosa nasconde l’attività del pigiare tasti su un joypad?A cosa può portare? Scopriamolo insieme.

———————————————-

 

Il Pentito

Il Pentito è un Insoddisfatto all’ultimo stadio. Mentre il secondo oscilla in un limbo di amore e odio per il medium ludico, il Pentito ha cambiato definitivamente sponda. I motivi per cui ci si pente sono molteplici e, più o meno, corrispondono a quelli per cui si è insoddisfatti. Ma in questo caso l’autodifesa arriva a spingere fino al disprezzo per quello che prima era l’hobby della vita.

Un tipo che abbandona i videogiochi non è la fine del mondo, verrebbe da dire. Peccato che questo frustrato ami girare per i forum pieni di videogiocatori per lasciare velati insulti tipo: “fatti una vita” “ho smesso perché ho scoperto la fica” “ho scoperto che praticare sport è molto meglio” “gli amici sono meglio” e altre amenità del genere. In questo modo il Pentito dimostra non solo di sentire ancora l’irrefrenabile desiderio di giocare, ma anche di essere un gran rompicoglioni.

In fondo questi esseri insulsi fanno pietà, perché dimostrano una debolezza estrema e senza speranza che li costringe a disprezzare quello che non possono più raggiungere.

Gioco preferito: ha smesso
Personaggio Preferito: ha smesso
Sogno Proibito (donna): ha smesso
Sogno Proibito (uomo): ha smesso

enl

read more