Tuesday, January 22, 2008

Buongiorno, vorrei una fettina di spazio. Senza grasso.

Ok, come accennavo ho trovato la soluzione, e a quanto pare funziona.
DirectX, come anticipato in precedenza, usa uno strumento chiamato "depth-buffer" per aiutarsi nel disegnare gli oggetti tridimensionali, evitando che vengano elaborati inutilmente pezzi che tanto non si vedranno.
Il problema è che il buffer fornito ha uno spazio limitato, o meglio, una precisione limitata.
E' uno strumento in grado di dire quali sono gli oggetti che stanno davanti, e quelli che stanno dietro, ma per farlo ha bisogno di appicicare un numero a ciascuno di questi componenti della scena.
"A te do il numero zero perche' sei lontanissimo"
"A te do il numero 1 perche' sei proprio davanti al mio naso"
"Tu che stai in mezzo ti do il numero 0.5".

E così via. Più il numero è grande e più l'oggetto e' vicino a noi.

Ora sarebbe bellissimo che questo strumento avesse tutti i numeri possibili ed immaginabili così da poter gestire anche casi tipo:
"Tu che stai due millimetri davanti a tizio ti do il numero 0.50000000000002"
"Tu che stai tra tizio e quello che e' appena andato a 2 millimetri di distanza, ti do il numero 0.50000000000001"
Purtroppo la realtà è che questo buffer può contare "solo" su 16 milioni circa di numeri.
Sembrano tantissimi ma in realtà non mi bastano affatto. Se infatti considero come distanza massima, ad esempio, la distanza tra il sole e giove (oltre il sole appare come un puntino e non ha nemmeno senso farsi troppi problemi), sono 816 081 455 km di distanza.
Diviso 16 milioni fa una tacca ogni 51 km, ovvero per due oggetti che distino tra loro meno di 51 km il buffer non ce la fa a dire quale dei due è avanti e quale dietro.
Ve l'ho un pò semplificata, in realtà le cose sono più complesse, e il depth-buffer comunque garantisce una maggior precisione per gli oggetti vicini, a discapito di quelli lontani (le prime tacche, a partir dal vostro naso, son tra di loro molto vicine, ma la distanza tra l'una e l'altra va via via aumentando man mano che si allontanano da voi) , ma concettualmente la questione sta esattamente in questi termini. Ecco quindi il perchè con tutto un universo da rappresentare, la scheda video si confonde quando due oggetti son tra di loro relativamente vicini. E purtroppo, come detto, per dar maggior precisione a ciò che ci sta vicino, viene trascurato quello che invece è molto lontano, assumendo che "tanto è lontano, vabbè farò dei pasticci, ma pazienza, in lontananza si vedrà piccolissimo, chi vuoi che se ne accorga". Già, ma nel mio caso i pianeti e gli astri son MOLTO grandi, quindi pur lontanissimi sono tutt'altro che minuscoli, ed ecco che appaiono le schifezze che vi ho fatto vedere nella puntata precedente.
Come si fa allora?
Beh, se il problema è fare stare quelle 16 milioni di tacche molto vicine tra di loro c'è poco da fare: o si aumentano il numero di tacche (e non si può), oppure occorre ridurre la distanza che devono ricoprire. Ridurre lo spazio però non mi va, altrimenti rischio di tornare verso ciò che non amo dei giochi visti fino ad oggi, ovvero dimensioni spaziali ridicole tipo "100 km tra il pianeta e il sole".

La soluzione che ho trovato leggendo in un forum, è una sorta di compromesso: faccio fare al depth buffer il lavoro di decidere chi disegnare prima e dopo solo all'interno di un oggetto complesso. Ovvero, considero la scena non più composta da migliaia di triangolini, come avveniva prima, ma piuttosto da "una sfera", "un'altra sfera", "un'astronave", ecc..
Al depht buffer do il compito di disegnarmi di volta in volta solo un oggetto coi suoi innumerevoli triangolini che lo compongono , quindi lui deve solo preoccuparsi che l'ala dell'astronave che sta dietro non appaia in quanto nascosta da quella davanti, dopodichè sarò io (la cpu) a disegnare i macro oggetti in ordine, dal più lontano al più vicino, visto che io (la cpu) ho tantissimi numeri in piu' rispetto alla scheda grafica, e non ho il problema di dovermi accontentare di 16 milioni.
Di contro la scheda video non dovrà più ragionare in termini di 800 milioni di km: se deve disegnare il sole ad esempio, ovvero l'oggetto più grosso, e se pensiamo di appoggiarci al nostro naso la superficie solare (dopo esserci messi abbondanti dosi di crema), il punto più lontano del sole disterà a questo punto da noi circa 600.000 km. E in questo caso la precisione è sufficiente. Gli altri oggetti poi sono tutti più piccoli.. et voilà!

Riassumendo quindi, decido di fare a fette lo spazio, in cubetti che avvolgono i vari oggetti, limito al volume dei cubetti l'azione della scheda video per disegnarli, dopodichè, ottenuti tutti i cubetti dipinti, sarà compito mio, ovvero il signor CPU, decidere qual è il più lontano e quale il più vicino, così li dispongo in ordine e vedrò tutto correttamente.

Certo, perdo l'ottimizzazione fatta dalla scheda video, se il sole sta dietro a giove, io comunque disegno tutto il sole, e poi ne ricopro un pezzo o tutto con il disegno di giove ma... onestamente con l'immensità dello spazio in gioco quante probabilità vi sono di avere un'eclisse?

2 comments:

Unknown said...

Complimenti, ma mi sfugge la soluzione dei cubetti...
In pratica disegni con l'hardware tante schermate (una per ogni oggetto) che poi incolli assieme con la cpu?

PdG said...

Si esatto. La soluzione standard e' quella di pensare un'unica tela e lasciare che la scheda video dipinga. Però, come detto, con un universo cosi' vasto non ce la fa.
Allora l'idea e' quella di fargli disegnare le cose a pezzettini, anziche' disegnar tutto lo spazio, disegnami solo la stella, poi solo il pianeta, poi l'astronave ecc.. Fa finta che la scheda disegni ciascuno di questi oggetti in un foglio trasparente, un foglio ogni oggetto.
Alla fine la cpu si ritrova tra le mani tanti foglietti contenente un disegno ciascuno, e deve trovare semplicemente l'ordine con cui sovrapporre i fogli in modo da ottenere l'immagine finale.