venerdì 29 marzo 2013

Movimento = Ridisegno + Scambio

La struttura di una animazione reale, non differisce molto da questa descrizione. Solitamente, è più facile ridisegnare l'intero buffer dall'inizio per ogni fotogramma, piuttosto che cercare di capire cosa deve essere ridisegnato. Ciò è verissimo per i simulatori di volo, nel quale un cambiamento dell'orientamento del mezzo, costringe al riposizionamento di tutto ciò che si vede fuori dall'abitacolo. Nella maggior parte delle animazioni, gli oggetti sono ridisegnati mediante semplici trasformazioni (un cambio del punto di vista dell'osservatore, o un veicolo che si muove lungo la strada, un oggetto ruotato leggermente). Se è necessario un lungo processo di calcolo per le operazioni non grafiche, il tasso di fotogrammi subisce un brusco calo. Da tenere in mente quindi, che il tempo di attesa dopo la routine scambia_i_buffer() , viene usato per questi calcoli. OpengGL non ha una routine di comando scambia_i_buffer() in quanto ciò è legato all'hardware disponibile ed al sistema di gestione delle finestre nella macchina sulla quale il programma viene eseguito.

domenica 17 marzo 2013

Il Refresh che mette in pausa

Per alcune implementazioni di OpenGL, inoltre la routine scambia_i_buffer(), oltre a invertire il buffer di memoria in disegno e quello visualizzato, aspetta sino a quando il periodo di rinfresco dello schermo non è concluso, e la schermata non viene visualizzata. Questa routine permette al nuovo buffer di memoria di essere visualizzato completamente, partendo dall'inizio. Assumendo una frequenza di 60 volte al secondo questo significa che il numero di fotogrammi massimi raggiungibili è di 60 frame per second (fps), e se tutti i frame sono azzerati in meno di un sessantesimo di secondo, l'animazione scorre fluidamente. Quel che può accadere solitamente è la costruzione di un fotogramma è troppo complessa per essere disegnata in 1/60 di secondo, pertanto il fotogramma vien mostrato più di una volta. Se il tempo necessario per calcolare è di 1/45 di secondo, la velocità raggiungibile di 30 fps, la grafica ha un tempo di ozio pari a 1/90 di secondo. Inoltre il tempo di rinfresco dei monitor è costante, pertanto bisogna aspettarsi delle conseguenze sulle prestazioni dell'applicazione. Bisogna valutare attentamente le caratteristiche dell'applicazione in fase di sviluppo, aggiungere delle componenti può non avere alcuna conseguenza sino ad un certo punto quando un nuovo componente del programma costringe il sistema a rallentare da 60 fps a 30 fps. Inoltre se la complessità della scena è prossima al valore intero (1/60, 1/30, 1/20) può subire variazioni casuali, le quali causano una visualizzazione irregolare, fastidiosa agli occhi di un osservatore. In questo caso è necessario semplificare la scena, in modo che tutti i frame siano abbastanza veloci, o rallentarli tutti allo stesso valore. Una gestione sofisticata del frame rate si rende necessaria in queste applicazioni.

venerdì 8 marzo 2013

Animazione con OpenGL

Una delle cose più eccitanti da fare con la grafica al computer è disegnare immagini in movimento. Che tu sia un ingegnere che vuole osservare un componente meccanico in tutti i lati, o un pilota che vuole imparare a far volare un aeroplano usando una simulazione, o semplicemente un appassionato; l'animazione è una parte importante della computer grafica. Al cinema il movimento viene ottenuto mediante una sequenza di immagini proiettate per un ventiquattresimo di secondo sullo schermo. Ogni immagine viene posta dietro l'obiettivo, il diaframma si apre e l'immagine vine mostrata; il diaframma si richiude temporaneamente, e la pellicola viene fatta avanzare di un fotogramma, quindi il fotogramma vien proiettato e così via. Se si osservano 24 immagini al secondo, il cervello umano provvede ad amalgamarle in un'unica sequenza animata. Di fatto i proiettori moderni mostrano un numero doppio di fotogrammi (48) al secondo per ridurre l'evanescenza. Le immagini in computer grafica sono solitamente rinfrescate alla velocità di 60 - 76 fotogrammi al secondo, il limite massimo è dio 120 fotogrammi al secondo. Ma per il tempo di risposta dell'occhio umano, superare questo limite non produce alcun effetto visibile. La ragione per cui i film funzionano è che ogni immagine è completa quando viene proiettata. Traducendolo in pseudo-linguaggio, si può scrivere:
apri_finestra();
per (i=0; i < 1000; i++) {
azzera_finestra();
disegna_fotogramma();
aspetta_tempo_1_24esimo_secondo();
}

Se si aggiunge al sistema il tempo per pulire lo schermo e disegnare un'immagine, questo programma può dare dei risultati non graditi in quanto si avvicinano pericolosamente a 1/24 di secondo. Gli oggetti visibili per 1/24 di secondo che presentano un'immagine solida in teoria, ma quando vengono disegnati dal computer possono apparire come spettri, in quanto il computer non fa in tempo ad azzerare l'immagine presente per sostituirla con un'altra. La maggior parte delle applicazioni OpenbGL consente il doppio buffering, via hardware o software, in modo da ridurre i tempi morti. Così mentre un'immagine viene mostrata, la successiva viene creata in memoria ed i due buffer sono scambiati di posto al termine della proiezione della prima immagine. Pertanto i due buffer lavorano in parallelo alternandosi nella proiezione, è come avere due proiettori contemporanei che proiettano lo stesso film alternandone i fotogrammi. Una versione modificata del programma si scrive in questo modo:
apri_finestra_in doppio_buffer();
per (i=0; i < 1000; i++) {
azzera_finestra();
disegna_fotogramma();
scambia_i_buffer();
}

lunedì 4 marzo 2013

GLUT, OpenGL Utility Toolkit

Come si sa OpenGL non contiene comandi di rendering, ma è progettato per essere indipendente dal sistema operativo e dalla gestione delle finestre. Di conseguenza, non contien comandi per aprire le finestre, o leggere eventi dal mouse o dalla tastiera. Sfortunatamente, è impossibile scrivere un programma di grafica completo senza almeno aprire una finestra, e i programmi più utili richiedono una forma di input da parte dell'utente per operare i comandi del sistema operativo e del sistema a finestra. In molti casi, un programma completo crea gli esempi più interessanti, in questo GLUT semplifica il sistema di gestione delle finestre, dell'input e così via. Se si possiede una implementazione di GLUT e OpenGL sul sistema, gli esempi mostrati saranno eseguiti senza problemi. Inoltre, i comandi di disegno delle OpenGL sono limitati al disegno di geometrie semplici quali punti, linee e poligoni; GLUT include alcune routine che permettono di creare oggetti 3D più complicati quali sfere, toroidi, teiere. In questo modo le immagini mostrate dai programmi sono rese più interessanti. GLUT può essere non molto soddisfacente come applicazione, ma può essere un buon punto di partenza per imparare OpenGL.

Gestione della Finestra

Cinque routine che eseguono i compiti necessari a gestire la finestra.
  • glutInit(int *argc, char **argv) inizia GLUT e processa ogni argomento di comando (per X, possono esserci opzioni sullo schermo e la geometria). glutInit() deve essere chiamata come prima GLUT routine.
  • glutInitDisplayMode(unsigned int modo) specifica se si vuole usare RGBA o modello di colore indicizzato. Si può anche specificare se si vuole finestra a singolo o doppio buffer. (Se si lavora con la mappa dei colori ne si vorrà caricare uno; usare glutSetColor() per farlo.) Infine si può usare la routine per indicare se si vuole una finestra associata ad un tipo di profondità, tratto, buffer di accumulazione. Per esempio si vuole creare una finestra con doppio buffering, e colore RGBA, bisogna chiamare: glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH).
  • glutInitWindowPosition(int x, int y) specifica localizzazione nello schermo partendo dall'angolo in lato a sinistra.
  • glutInitWindowSize(int larghezza int taglia) specifica larghezza e altezza della finestra.
  • int glutCreateWindow(char *stringa) crea la finestra del contesto OpenGL. Restituisce un indicatore unico per la finestra. Avvertenza, sino a quando glutMainLoop() viene chiamato la finestra non è visualizzata.
      

    Le chiamate alla Visualizzazione


    glutDisplayFunc(void (*func)(void)) è la prima e la più importante funzione di chiamata alla visualizzazione. Non appena GLUT determina il contesto della finestra che deve essere visualizzata, la chiamata alla funzione registrata mediante glutDisplayFunc() viene eseguita. Pertanto le routines di cui si ha bisogno per ridisegnare la scena nello schermo attraverso il richiamo della funzione.

    Se il programma cambia i contenuti della finestra, a volte bisogna richiamare glutPostRedisplay(void), il quale fornisce una scappatoia a glutMainLoop() funzione per essere richiamata mediante questa nuove opportunità.

    Eseguire il programma

    L'ultima funzione da richiamare è glutMainLoop(void). Tutte le finestre che sono state create vengono mostrare, e il rendering di queste è ora effettivo. Il processo degli eventi comincia ed avviata la registrazione degli eventi a schermo. Una volta entrati nell'anello, non se ne esce.

domenica 3 marzo 2013

File inclusione OpenGL

Per tutte le applicazioni OpenGL è necessario includere il file gl.h. Quasi tutte le applicaizoni OpenGL usano GLU la sopramenzionata OpenGL Utility Library. Così quasi ogni file sorgente OpenGL inizia con:
#include <gl.h>
#include<glu.h>

Se si sta accedendo direttamente alla libreria di interfaccia della finestra per supportare OpenGL come GLX, AGL, PGL, WGL si devono includere file addizionali di header. Ad esempio per richiamare GLX può essere necessario aggiungere le linee di codice:
#include <X11/xlib.h>
#include<GL/glx.h>

Se invece si sta utilizzando GLUT per gestire le funzioni della finestra, bisogna includere il codice:
#include<GL/glut.h>

Non è necessario includere tutti i file intestazione automaticamente, ma è necessario sceglierli. GLUT include tutte le funzioni contenute in WGL per Microsoft Windows.