Introduzione alla grafica 3D (by Patrizio Tamorri)
da Gaio Giulio Patrizio, in Informatica Libera | 10 settembre 2008 @ 12:07 | 2 commentiLa grafica 3d è una cosa che molti credono un concetto inavvicinabile. Complicate operazioni matematiche e trasformazioni matriciali sembrano in grado di spaventare chiunque…E’ quindi il momento di farvi passare la paura.
Qui vi illustrerò come un triangolo viene disegnato a schermo. Con questo semplice concetto potrete poi disegnare a schermo ciò che vorrete visto che tutti gli oggetti sono rappresentabili da triangoli.
Innanzitutto vediamo i concetti di base. Nel nostro mondo virtuale ci occorre un origine, un punto 0.
Matematicamente esso è l’incrocio degli assi. Rispetto a questo punto definiremo le coordinate X, Y e Z del nostro ipotetico mondo virtuale. Avremo dunque 3 punti nello spazio che identificano il nostro triangolo 3d ognuno con le precedenti 3 coordinate che lo collocano nello spazio rispetto all’origine.
Fin qui mi direte: Mamma mia a questo ci arrivavo anche da solo.
Ma come ce lo metto su un o schermo?
Qui inizia una parte un po piu complicata. Innanzitutto dovete avere un punto di questo spazio che chiameremo telecamera. Il punto telecamera come immaginerete è il punto da cui stiamo vedendo il nostro triangolo.
Ma manca ancora qualcosa per poter vedere il nostro mondo. Manca la direzione in cui stiamo guardando. Se noi avessimo la nostra testa in un punto di quello spazio e non sappiamo dove stiamo guardando, come faremo a sapere cosa vediamo?
Qui qualcuno potrebbe pensare a usare un vettore che indichi la direzione ma invece noi useremo una matrice. AAAAAAHHHHH. Un boato assordante mi raggiunge mentre leggete questa frase. Tranquilli. Una matrice è un sistema per risolvere principalmente sistemi di equazioni.
Una cosa del genere ad esempio:
3* X + 5*Y + 3*Z = 4
4* X + 1*Y + 3*Z = 6
3* X + 2*Y + 4*Z = 2
la potete risolvere facendo la seguente operazione matriciale:
|3 5 3 4|
|4 1 3 6|
|3 2 4 2|
e trovandone il determinante.
Difatti potete rappresentare attraverso una serie di matrici particolari le seguenti operazioni: Traslazione di un punto, Rotazione, Scala (potete aumentare ogni distanza tra due punti del 50% ad esempio).
Ecco ad esempio la matrice necessaria per effettuare una rotazione su un asse qualsiasi X, Y o Z
1 0 0 0
0 cos sin 0
0 -sin cos 0
0 0 0 1
Questa matrice di per se non fa niente. Ma se la moltiplicate per il valore della coordinata da ruotare e poi sostituite il valore precendente con quello nuovo otterrete un punto ruotato. In pratica per ruotare sull’asse X di 45 gradi un punto T si deve fare:
X del punto da ruotare = “Matrice vista prima con cos e sin sostituiti con cos di 45 e sin di 45 gradi”
moltiplicata con prodotto scalare per il valore della X del punto da ruotare.
Facile no? Le matrici particolari per fare ogni operazione si trovano in ogni sito internet se volete provare altre. Il funzionamento è uguale. Di bello le matrici hanno che se le moltiplicate tra loro gli effetti si sommano. Ad esempio moltiplicate una rotazione per una traslazione e avrete una roto-traslazione ;)
Tornando al discorso di prima al nostro punto camera assoceremo una matrice che chiameremo di “World To Camera Space”. In pratica questa matrice prenderà ogni punto del grafo con le sue coordinate riferite al punto di origine (lo zero di prima) e le trasformerà in camera space (ovvero ogni punto avrà come origine il punto telecamera. Se ci pensate è come se avessimo spostato ogni punto insieme alla telecamera e avessimo posto al telecamera sul punto di origine).
Ora però manca qualcosa. Questa operazione di per se non sembra averci fatto guadagnare molto. Ora abbiamo ogni punto e la sua posizione rispetto alla telecamera ma non sappiamo ancora dove guarda ’sta telecamera. Definiamo quindi una matrice che identifichi dove stiamo guardando. La sua derivazione è complicata ma le DirectX se vi può fare comodo usano la seguente definizione:
pEye
Vettore che contiene la X, Y e Z del punto della telecamera.
pAt
Vettore che identifica dove guarda la telecamera.
pUp
Vettore che punta in alto. In genere è [0, 1, 0], ovvero la Y positiva è l’alto.
Potete ottenere effetti carini cambiando questa proprietà come ad esempio rotazioni i quello che vedete.
zaxis = normal(At - Eye)
xaxis = normal(cross(Up, zaxis))
yaxis = cross(zaxis, xaxis)xaxis.x yaxis.x zaxis.x 0
xaxis.y yaxis.y zaxis.y 0
xaxis.z yaxis.z zaxis.z 0
-dot(xaxis, eye) -dot(yaxis, eye) -dot(zaxis, eye) 1
dove quelle indicate sono le classiche operazioni tra vettori come normale, prodotto scalare (dot) e vettoriale (cross).
In genere qualsiasi libreria userete (OpenGL o DirectX) vi metterà a disposizione una funzione che ve lo fa automaticamente. In DirectX è D3DXMatrixLookAtLH.
Ora che avete questa matrice in genere ogni algoritmo che faccia Rendering (ovvero che scriva a schermo oggetti 3d o 2d) in questa fase fa il cosiddetto clipping ovvero sceglie quali triangoli renderizzare (ovvero disegnare a schermo). A noi non interessa al momento. Abbiamo un solo triangolo =).
Finora abbiamo quindi:
1) Ottenuto un mondo 3d anche se piccolo con riferimento a un punto origine.
2) Trasformato ogni punto in camera space.
3) Creato una matrice che ci indica dove stiamo guardando. In pratica adesso ogni punto verrà ruotato rispetto alla telecamera (che si trova nell’origine) e avrò quindi un ambiente in cui posso determinare gli oggetti visibili.

Come vedete nell’ultima immagine ho praticamente solo aggiustato il mondo in modo che abbia la mia visuale centrata sull’asse Z (la c della figura) dalla situazione scomoda iniziale.
Ora resta un passo da fare. Capire quanto sono vicini e lontani i vari oggetti. Un oggetto lontano appare più piccolo di uno vicino. Questa proprietà è però un po’ complessa perché a differenza di come siamo abituati a disegnare in genere un oggetto non diventa più piccolo in maniera lineare ma si basa sulle leggi ben più complesse della prospettiva. Non voglio entrare nei dettagli ma per chi ne vuole sapere di più ecco la descrizione della documentazione DirectX su come computarla.
fovy
ampiezza campo visivo Y, in radianti
Aspect
Aspetto dello schermo. Vi sarà capitato di vedere che il vostro monitor è a 800/600 = 4/3 = larghezza/ampiezza. Quelli dei cinema sono più stretti infatti spesso ci mettono le barre sopra e sotto quando trasportano i film per la tv.
zn
Piano più vicino. In pratica quanto volete vedere vicino (vertici più vicini non li vedrete)
zf
Piano più lontano.
yScale = cot(fovy/2) ovvero la cotangente
xScale = yScale / aspect ratioxScale 0 0 0
0 yScale 0 0
0 0 zf/(zf-zn) 1
0 0 -zn*zf/(zf-zn) 0
where:
Anche qui in genere ci sono le funzioni apposta quindi fanno loro ;)
Ora avete tutto in regola per scrivere a schermo. Basterà far passare ogni vertice per
1) la trasformazione in camera space (moltiplicazione tra matrice e coordinata) ovvero la funzione vista prima che in DirectX si otteneva chiamando D3DXMatrixLookAtLH.
2) la trasformazione di proiezione che è l’ultima che abbiamo visto.
Ora avrete le coordinate fisiche su cui scrivere a schermo i vostri vertici.
Chiaramente questa escursione nel mondo del 3d manca di moltissime cose ma è una base per farvi capire come funzionano le principali meccaniche che stanno dietro ai giochi che vedete in giro oggi.
Tag: 3D, directx, grafica, ilbloggatore, informatica, programmazione, tecnologia, videogiochi














Hai ragione qui i commenti erano bloccati :/ ma non chiedermi perché.. è stato il koteko a postare, tutta colpa sua!! =P
Che te pozzano Tik.Mi blocchi gli articoli XD
Ciao dal partrik