Orizzonti Lontani

Oggi mi piacerebbe discutere con voi di una tematica piuttosto complicata: quella dei famosi “spazi aperti”.

Sulle riviste e sui forum si discute di quale sia il gioco con gli spazi più ampi o di quale engine sia più capace di fare cosa.

Ma come facciamo a capire quando uno “spazio” è ampio?

In primo luogo cerchiamo di capire la problematica: perchè disegnare uno spazio ampio è un problema?

Per due motivi:

  • Grande quantità di poligoni
  • Grande quantità di materiali
Perchè ho scritto “materiali” e non “texture”? Perchè la texture non è l’unica cosa che appesantisce la pipeline di rendering: anche un semplice cambio di stato la appesantisce.
Possiamo quindi definire un gigantesco quadrato con sopra una texture uno “spazio ampio”?
Dal punto di vista letterale, sì, ovviamente: il quadrato è enorme. Per questo è più corretto utilizzare il termine inglese “Large Environment”, che in sè condensa la grande dimensione dal punto di vista del dato, rispetto al punto di vista visivo.
Purtroppo questo punto è molto difficile da capire, quindi insisterò maggiormente per far capire cosa intendo.
Prendiamo una cartolina qualunque:
Questa è una foto della mia amatissima Champoluc vista dall’alto. Proviamo ad immaginare di dover fare il rendering in tempo reale di questa immagine.
Facciamo finta che ogni casa sia modellata in maniera realistica, con circa 25000 poligoni e 3MB di texture.
Possiamo facilmente intuire che questa scena (solo con le case) prevede circa 1.000.000 poligoni e 120 MB di texture.
Se solo ci fossero le case, la scena sarebbe già abbastanza pesantina. Aggiungiamoci gli alberi (saranno almeno trecento), aggiungiamoci l’illuminazione e il terreno ed ecco che abbiamo una scena che non può essere in alcun modo presentata così com’è alla scheda grafica.
In più consideriamo che, se fosse un gioco, non potrebbe esserci solo questo: appena giriamo la testa dovrà esserci tutto il resto del mondo.
Possiamo quindi già tirare una conclusione: qualunque engine potrebbe mostrare ambienti ricchissimi, se avesse a disposizione un hardware potentissimo.
Quindi: come facciamo a mostrare una scena come quella sopra ad un framerate di (diciamo) 30 fps?
In primo luogo dobbiamo capire cosa significa “30fps”: significa avere circa 32 millisecondi ad ogni frame.
Non molto.
30 fps x 1.000.000 = 30.000.000 di poligoni
Un po’ tanti.
Consideriamo che non abbiamo tutti i millisecondi per noi: c’è anche il gioco in sè che vuole la sua parte.
Ok, possiamo partire a valutare i problemi:

TEXTURES e MATERIALI

Il problema è talmente noto che la soluzione è già stata trovata da quando si fa grafica in tempo reale.
La prima scrematura si fa sulla distanza: perchè usare le texture 2048×2048 quando le case sono così lontante? Basta usare texture 256×256. Facendo così, si riduce drasticamente il tempo di campionamento delle texture.
Questo si chiama “Mipmapping” e non funziona solo sulla lontananza dall’oggetto, ma anche dalla sua posizione rispetto alla camera: più l’oggetto è “di sbieco” più la texture utilizzabile è piccola.
Perfetto, ma questo non basta: una singola casa ha un bel po’ di materiali (il tetto innevato, le finestre, il legno, il muro). Ognuno di questi materiali avrà dei parametri, delle texture e degli stati hardware da settare.
Per ridurre il cambio di stati, possiamo raccogliere per bene tutti gli oggetti col medesimo materiale e disegnarli tutti assieme.
Alcune architetture sono terribilmente più veloci se si riduce il numero di chiamate alla funzione di render, ma passando tanti triangoli: potremmo fare anche così. Questo non è banale per nulla, quindi se decidiamo di farlo, dovremo essere certi che l’architettura sulla quale lavoriamo ci fornisca un boost molto ampio.
Il PC in generale è una di queste architetture, per esempio.

Numero di Primitive

Parlando terra terra, una primitiva è un triangolo. Non è sempre così (OpenGl ad esempio prevede triangoli, punti, linee, quadrati e poligoni), ma possiamo facilmente dire che è così nel 99% dei casi.
La regola principale nel campo della computer grafica è: il modo più veloce per fare una cosa è non farla.
Quindi: qual’è il modo più veloce per disegnare un sacco di triangoli? Risposta: disegnarne pochi.
Ma come possiamo fare? Nella storia ci sono state mille e mille soluzioni. Vediamone qualcuna:
Riduzione del livello di dettaglio: se un oggetto è lontano, possono bastare pochi poligoni per descrivere la sua forma, rispetto a quando è vicino. Ci sono algoritmi che riducono il numero di poligoni in tempo reale (algoritmi “continui”) oppure è possibile utilizzare N modelli 3D prefabbricati, con sempre meno triangoli (algoritmi “discreti”).
Eliminazione degli oggetti fuori dal campo visivo: se un oggetto non è nel campo visivo (frustum) si può evitare di mandarlo in rendering. il controllo si chiama “frustum test” ed in genere si fa per oggetto.
Eliminazione dei triangoli fuori dal campo visivo: questo punto si differenzia dal precedente perchè la precisione scende al triangolo. Tal sorta di test si fa in genere su modelli 3d di grandi dimensioni (come i terreni o gli ambienti), che altrimenti sarebbero sempre in camera e sarebbero sempre disegnati per intero, poiché ben più grandi di quello che la camera può vedere. Per risolvere questo problema ci sono varie soluzioni, come gli OctTree, una struttura dati che consente di partizionare lo spazio e di fare velocemente i conti per decidere “chi è dentro e chi è fuori”, oppure il “Potential Visible Set“, un sistema che divide (in preprocessing) tutto il mondo in blocconi e decide quali oggetti siano visibili nei vari settori. Se un triangolo non è mai visibile, potrebbe essere semplicemente eliminato dalla scena.
Eliminazione dei triangoli coperti da altri triangoli: Il test che si compie, in questo caso si chiama “Occlusion Test” o “Visibility Test”. Un sistema per eseguirlo è utilizzando i “Binary Space Partition Trees”, amati da sempre da Id Software.
Ognuno di questi sistemi (più i mille altri che non ho citato) servono ad evitare di disegnare tutto ciò che non serve, in modo da mandare alla scheda grafica la quantità minore di triangoli (od oggetti) possibile.

Oggetti Ripetuti

Se guardiamo la scena, notiamo che ci sono una quantità troppo elevata di alberi. Da soli, questi alberi, rischiano di prendere interamente tutto il tempo che abbiamo per fare il nostro rendering. Come fare?
Qui abbiamo fondamentalmente due soluzioni, a seconda dell’hardware che abbiamo a disposizione: se l’hardware supporta l’instancing, possiamo mandare un singolo modello 3d di albero, seguito dalle informazioni necessarie per il rendering per ogni albero che vogliamo. Ad esempio, possiamo mandare l’albero e poi cento posizioni diverse, così l’hardware disegnerà questo albero cento volte in queste cento posizioni.

Conclusione

Dopo tutto questo articolo, cosa possiamo dire? Possiamo dire che se un engine non supporta tutte queste feature, allora non supporta gli spazi aperti? No, non possiamo dirlo.
Perchè? Perchè se abbiamo un megaPC pazzesco, con tantissima RAM ed una scheda grafica pazzesca ed immensa, possiamo completamente ignorare tutti i problemi di cui sopra e mandare alla scheda quei 30 milioni di triangoli al secondo, oppure quei gigabyte di texture, tanto il sistema è potente e reggerà il colpo.
Il problema, per i progettisti, è pensare a dei sistemi per far girare questi ambienti su computer esistenti.
Proviamo a pensare a “Grand Theft Auto San Andreas”: non voglio nemmeno immaginare da quanti poligoni e texture sia composto il mondo. Nonostante questo, gira su una PS2 a 30 fps (o 60?). Se tutte queste tecnologie non fossero implementate, non girerebbe mai su una PS2.
Quindi, ora, sapendo questo, poniamoci questo quesito: ha senso chiedere se un engine supporta gli spazi aperti? Viste le migliaia di possibilità dietro questa domanda, io dico di no.
Ha senso, allora, chiedere quanti poligoni e che mole di texture può disegnare un dato engine con un dato PC garantendo i 30 (o 60) fps? Questa domanda ha molto senso, ma capirete bene che non è un equivalente della precedente: se dieci anni fa 500.000 triangoli e 100MB di texture per tutto il mondo potevano essere un “Large Environment”, oggi come oggi questi numeri sono decisamente cambiati.
Quindi, quando vi trovate in una discussione sulla capacità o meno di un engine di disegnare i dannatissimi spazi aperti, cercate sempre di capire con chi state parlando: se è un giornalista o un videogiocatore fanatico del PC, allora molto probabilmente sarà meglio non entrare nemmeno nel discorso 🙂

La Parte più Difficile

In attesa di finire un grosso articolo, vi sollazzerò con qualche rilessione.

Vi siete mai chiesti quale sia la parte più complessa nel fare un gioco? Io, quando ero più giovine, talune volte me lo chiedevo.

In generale, ho sempre ritenuto che la parte complessa fosse l’engine 3D, o comunque tutta la parte grafica.

Questo dev’essere stato un po’ il pensiero di tutti quanti, difatti, cercando su Internet, si trovano una valanga di engine già fatti (tra cui mi viene in mente Ogre e Irrilicht), ma bel poco di tutto il resto.

Oggi è spuntato un nuovo tema: gli engine fisici. Sviluppare un engine fisico è una cosa praticamente impossibile se non si ha una formazione dal punto di vista della fisica, ma fattibile (se vengono dati il giusto tempo e le giuste risorse) da chi invece ce l’ha.

Io non ho una formazione fisica adeguata ed immagino che molti miei colleghi non l’abbiano, difatti ci sono molti engine fisici disponibili.

Ma il resto? Il resto è tanto banale? No, assolutamente. Spesso leggiamo sulle riviste frasi come: “Che ci voleva aggiungere questo e quello? E’ banale!”

Beh, purtroppo, non esiste niente di banale. Purtroppo, l’ultima frase non era una frase fatta.

Una cosa considerata semplice e sottovalutata (fino all’avvento del Wii) è l’input, ad esempio.

Proviamo a pensarci: l’input è una cosa che avviene in maniera del tutto asincrona (ossia, quando uno schiaccia, schiaccia 😀 ), in più cambia da piattaforma a piattaforma.

Su PS2, ad esempio, abbiamo due stick analogici, un po’ di tasti analogici e qualche tasto binario (schiacciato/non schiacciato).

Su 360 abbiamo una roba simile, ma sbilanciata sui tasti binari. Su PC abbiamo un milione di tasti binari ed un mouse.

Poi arriva il Wii con i suoi due accelerometri, il suo puntatore ed i suoi tasti.

In più l’Input varia a seconda di dove siamo: nei menù ci sarà un tipo di Input, mentre nel resto del gioco un’altro tipo.

La gestione non è banale.

Ho detto menù? Ecco un vero massacro.

Gestire i menù è un problema sottovalutato, difatti non si trovano molte librerie. Le uniche buone, tra l’altro, sono a pagamento. Un SONTUOSO pagamento.

Perchè?

Perchè creare menù non significa solo scegliere qualcosa su schermo, significa tutto questo:

  • – Dare ad un grafico uno strumento per fare i menù
  • – Agganciare gli eventi dei menù a del codice
  • – Gestire una serie di controlli standard.
  • – Andare su più piattaforme.

Un’idea è usare Flash: il formato è noto e i grafici lo conoscono già.

In più non bisogna farsi lo strumento per i grafici.

Purtroppo facendo così complica molto la possibilità di fare menù con elementi 3D: Flash non lo supporta.

Credo di poter stimare che una gestione dei menù e degli overprint (ossia la roba 2d che sta sul 3d, tipo le barre di energia) copra tranquillamente un buon 20% nel making di un gioco ed un 40% del making dei tools.

Un’altra cosa spesso sottovalutata è la faccenda dei save-game. I Save-game ad oggi sono considerati assolutamente standard ed un gioco che non li abbia è considerato “limitato”, almeno su PC.

Ma perchè su PC i save-game sono fattibili “in ogni momento” mentre su console in genere ci sono i checkpoint?

Semplice: anche i save-game non sono un problema banale 😀

Pensiamoci un secondo: se voglio salvare in ogni momento, in un FPS, dovrò salvare la mia posizione, il livello in cui sono, la posizione dei nemici ed il loro stato, tutti i miei dati e tutto quello che concerne la roba già fatta (oggetti, dialoghi già seguiti e cose simili).

Se ho i checkpoint, salvo in che checkpoint sono, i miei dati ed ho risolto 🙂

La differenza sta nella dimensione: sulle console vecchie (Ps2 in giù) lo spazio per i savegame era molto limitato.

Poi ci sono i casi in cui si può salvare dove si vuole anche su console. Questo dimostra che in questo caso i save-game sono stati oggetti di analisi e di ottimizzazione.

Niente di banale, quindi.

Purtroppo il mondo è così: guardiamo i poligoni e pensiamo che il subsurface scattering (che parolone 😀 Usatelo per stupire gli amici) sia la cosa più difficile che vediamo sullo schermo, mentre probabilmente ha richiesto 3 giorni.

Il sistema che disegna e gestisce il menù dei personaggi di Final Fantasy 6, invece, probabilmente di giorni ne ha richiesti almeno il triplo (se non il decuplo).

Beh, dopotutto tutti noi lo sappiamo: il mondo è ingiusto 🙂

L’Audio, il senso vituperato

Io amo la musica. Mi ci sono dedicato anima e corpo per più di quindici anni, raggiungendo risultati che non avrei mai sperato, tra cui il Master di Chitarra Rock di Begotti e il mio primo disco pubblicato.

La amo proprio, la musica. Pensate che talune volte, alcuni giochi non tanto belli vengono da me salvati perchè hanno una bella musica, o un bell’audio in generale.

Non la grafica: quella non mi è mai bastata per salvare un gioco mediocre.

Sembra che io sia l’unico, altrimenti non ci spiegheremmo perchè i computer vengono venduti con schede video pazzesche e schede audio poco migliori della Sound Blaster.

Non capisco: sono dell’idea che l’audio sappia creare tutti i sentimenti possibili, anche ad occhi chiusi. Proprio l’altro giorno giocavo a “Scratches”: bene, in questo gioco la grafica è poco più che mediocre, mentre l’aspetto tecnico è vecchio di almeno dieci anni.

Tutto è fermo, statico, come non mi capitava di vedere dai tempi di Myst. L’audio è splendido. Questo gioco mi piace.

Quello che noto molto spesso è che i giocatori, piuttosto spesso, nemmeno giocano con l’audio acceso. Senza senso.

Ultimamente ho provato un po’ di giochi con un audio molto buono: Persona 3, Mario Galaxy e Portal. Nel contempo ho provato una barca di giochi dove l’audio a stento c’è, ma la grafica quella sì che è una figata.

Prendo un caso ecclatante: Eternal Sonata. Belle le musiche, vero? Certo! Sono uguali a quelle di Tales of Symphonia, che erano belle, quindi sono belle.

Gears of War? Quattro effetti sonoro e due Jingle.

Halo 3? Belle le musiche, non c’è dubbio. Sono le stesse da dieci anni.

Dopotutto non posso neanche farne una colpa: quando i distributori rilasciano qualcosa, rilasciano degli screen, così i giocatori potranno trovarci tutti i difetti del mondo e dire che il gioco fa schifo.

Oppure potranno difenderlo a spada tratta perchè si chiama PES.

Di certo non si mettono a postare frammenti di audio: chi se ne frega? Gli utenti di oggi potrebbero anche non averle le orecchie: non noterebbero nessuna differenza.

Il lavoro più agognato

Game designer

Credo che il lavoro di cui più si parla ma meno si sa sia quello di game designer.

Esistono corsi che spiegano come diventarlo, ma qui lo dico e qui lo confermo, prendendomi tutta la responsabilità di questa frase: i corsi (universitari o meno) per diventare game designer sono una perdita di tempo e di soldi. Non fateli e non supportate chi li fa: vi ruba tempo e soldi.

Bene, detto questo, cosa fa un game designer? Beh, la Leggenda vuole che

il Santissimo Game Designer plasmi i sogni e ne faccia ludo.

La Leggenda non è troppo distante dalla realtà, ma vediamo cosa fa esattamente il game designer (da ora GD).

Prima di tutto pensa all’idea, ovviamente. Fatto questo, la stende utilizzando documenti standard, in modo che il lettore saprà dove trovare tutto quanto.

E questa è la parte breve.

Poi viene la parte lunga: il tuning. Il GD, una volta che ha in mano un prototipo, lo gioca fino ad averlo in odio e lo rende il più giocabile possibile, tunando i valori che vengono forniti. Spesso (SPESSO) ne chiede di nuovi, poiché dopo aver visto com’è il gioco, di certo vorrà altre cose.

Quindi come deve fare un ragazzo per diventare GD? Deve laurearsi in lettere? Ma va’ là! Deve giocare. Deve giocare a tutti i giochi del mondo e deve saper capire cosa va bene e cosa no.

Poi deve entrare in una piccola società, magari che fa giochi per cellulari. Da lì potrà partire.

Taluni hanno raggiunto lo scopo grazie a concorsi (tipo quello di TGM di qualche anno fa).

Ma è tutto sollazzo? No, anzi: quando vi chiederanno di mettere giù un design per i menù, facendo delle semplici bozze di ogni pagina, vorrete aver scelto di fare il tappezziere. Tutti i lavori hanno la loro parte pallosa, dopo tutto.

Ora vediamo il maggior nemico del GD: se stesso.

Perché? Perché ogni GD ritiene di avere l’idea definitiva per il gioco incredibile e perfetto. Molto spesso questa idea richiederebbe un budget pari al PIL annuale dell’America, ma lui sa che se qualcuno lo facesse, allora venderebbe moltissimo.

Il GD deve quindi avere bene in mente cosa significa “fare un gioco con un dato budget”, quindi saprà che ci saranno cose che non ha senso chiedere.

Ad esempio, supponiamo che mi arrivi questo design:

“Voglio fare un gioco tipo Oblivion, ma più ricco e complesso”. Poi seguono 300 pagine di spiegazione.

Purtroppo lo cestinerò, anche se magari sarebbe un gioco pazzesco.

Sembrerebbe quasi che il GD debba conoscere le evoluzioni della tecnologia. Verissimo, ma lui deve sapere cosa sono ad un livello molto alto. Se non conosce le nuove potenzialità, allora parlerà con il capo programmatore, per sapere cosa può chiedere e cosa no. Oppure chiederà e si vedrà le feature tagliate.

Un’altra cosa che il GD deve sapere è che un gioco deve essere DIVERTENTE. Non REALISTICO o SIMULATIVO o SUPERFIGO.

La prima parola deve essere sempre “DIVERTENTE”. E’ divertente un simulatore perfetto di intestino? No.

Ma sarebbe divertente un simulatore del corpo umano con gli omini tipo “Esplorando il corpo umano” e facendolo tipo “Warcraft”? Boh, forse sì, se si mette giù bene.

Veniamo ora al modo di lavorare.

Nessuno si aspetta che il design venga chiuso il giorno X e non venga mai più riaperto. Sarebbe una grave mancanza di esperienza da parte della produzione. Il designer può apportare modifiche, tagliare feature e generalmente fare cambi alle interfaccie durante tutta la vita del prodotto.

Quello che è MOLTO bene non faccia è cambiare quelle parti che richiedono un completo ripensamento. Prendiamo un esempio: da sempre, da design, un’avventura grafica sarebbe dovuta essere a “tempo statico”, cioè il tempo non passa in gioco e gli eventi accadono grazie a dei trigger.

Di colpo il designer decide che invece il tempo sarà effettivo e gli eventi accadranno in vari momenti del tempo, che noi ci siamo o no. Questo richiede, ovviamente un cambio completo del gioco. Questo cambio potrebbe essere semplicemente tagliato, ma avrebbe portato a tempo perso del designer: tempo che poteva dedicare al tuning degli hotspot (in un’avventura grafica sono fondamentali).

Molto più grave è una cosa del tipo: “Sarebbe figo avere in gioco dei personaggi non giocanti, che facciano cose semplici, niente di complesso”, sempre nella nostra avventura grafica. Bene, se prima non era previsto, significherà che i programmatori dovranno aggiungere un elemento “alla bell’emmeglio”, poiché tutte le strutture dati ed i salvataggi non prevedevano una cosa del genere.

Il problema di queste richieste “vorrei una cosa semplice, così tanto per” non andranno mai bene, perché una feature appena abbozzata fa SEMPRE schifo. Quindi, dopo che si saranno ficcati questi personaggi nella nostra avventura grafica, è praticamente sicuro che faranno schifo ed il loro comportamento sarà sì semplice, ma orribile.

Finale della storia: i personaggi verranno tolti e si sarà perso tempo. Il tempo è danaro, quindi si saranno persi soldi.

Quindi è assolutamente fondamentale che il GD sappia identificare quelle tematiche che fanno da “mattoni portanti” del videogioco. Quelle feature non dovranno mai essere toccate, perché nel momento in cui si decide di NON fare qualcosa, gli ingegneri ottimizzeranno il tutto intorno a quella mancanza.

Bisogna anche saper identificare cosa invece NON è un mattone portante. Tutti gli asset grafici, ad esempio, non lo sono.

Credo che questo insegnamento sia forse uno dei più importanti che possano essere trasmessi.

La critica potrebbe essere che forse sarebbe meglio anticipare il cambiamento, facendo dei framework molto duttili. Questo è vero, ma la duttilità, se troppo spinta, si paga in complessità, molto spesso “complessità di utilizzo”.

Quindi riassumiamo cosa deve fare il GD:

  • Scrivere il documento di design (ci sono ottimi esempi su GPI)
  • Tunare il gioco, chiedendo modifiche
  • Progettare le interfacce

Cosa bisogna fare invece per diventarlo?

  • Entrare in piccole compagnie che si occupano di entertainment
  • Giocare a centomila giochi
  • Capire cosa è divertente e cosa invece no
  • Capire cosa è importante e cosa invece no

Alla prossima!

La Lingua del Ludo

Talune volte frequento il newsgroup it.comp.giochi.sviluppo e spesso leggo l’annosa domanda: “Che linguaggio si usa per fare videogiochi?”

Un tempo la risposta sarebbe stata semplice: “Il C++, mio buon amico”. Anni ancora prima, la riposta sarebbe stata ancora più sgraziata “Il C, per l’amore diddio”.

Se andiamo ancora nel passato, allora sarebbe stata “L’assembly, you fuckin’ noob”.

E oggi? Finalmente possiamo dire “dipende”. Aaah la libertà! Tanto bella quanto pericolosa.

E da cosa dipende? Dipende da cosa dobbiamo fare. Non parlo della “complessità”, ma della “mansione”.

Dobbiamo fare Tool, l’Engine o il Gioco?

Nei tre casi le nostre competenze richieste saranno diverse. Se facciamo l’Engine, ad esempio, non si può scappare: tutti gli SDK di tutte le console sono in C o C++.

Ma se facciamo il gioco? Beh, in quel caso, immaginiamo di utilizzare “Virtools”: questo strumento si programma con degli script.

Oppure, ancora, Macromedia Director o il sistema “Vicious Engine“: tutti questi sistemi si programmano con degli script.

Oppure supponiamo che l’engine sia stato fatto in modo che tutte le chiamate si possa usare, chessò, in Phyton: così facendo il programmatore del gioco deve conoscere Phyton e non il C++.

Se devo fare i Tools, ho varie scelte: potrei dover conoscere il linguaggio che usa l’engine (il C++, o il binding il Phyton), oppure, se devo fare roba per 3d Studio Max, dovrei conoscere MaxScript.

Ed ecco fatto! Abbiamo un bel po’ di figure professionali che non devono sapere il C++, ma lavorano nei videogiochi.

Se poi aggiungiamo che magari le pagine di menù vengono fatte in Flash, opplà! Abbiamo miliardi di papabili Falshisti che potremmo usare per programmare le nostre pagine.

Porto qualche esempio, in modo da capirci: Valve software ha l’engine in C++, ma i tools in C#. In questo modo ha i tools fatti in un linguaggio che toglie moltissimi problemi di gestione della memoria, è molto produttivo e consente di fare interfacce grafiche in pochissimo tempo.

Battlefield è fatto in larga parte in Phyton, mentre l’AI e tutti gli eventi scriptati di Crysis e Far Cry sono fatti in LUA, un altro linguaggio di scripting molto in voga.

Tutte le avventure grafiche Lucas sono state fatte con lo storico SCUMM, un sistema a script.

Dopo tutto questo discorso, capiamo che, ad oggi, la risposta “Il C++ o Morte!” E’ obsoleta. Obsoletissima!

E l’ottimizzazione storica che fa il C++? Eeeh, ci ricolleghiamo al precedente articolo, ma temo che ci sarà ancora da parlare parecchio su questo argomento.

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.