Corso di DirectX

Il primo programma DirectX (II)

 

Usare i messaggi

Continuiamo il discorso dalla lezione precedente. Dopo aver creato il 3dDevice, siamo pronti ad utilizzarlo per disegnare qualche figura sullo schermo. Ma, come molti di voi sapranno, un programma per Windows deve seguire certe regole. Una di queste è che il corpo principale del programma si occupa di ricevere messaggi e di agire in base ad essi. Perciò il nostro programma DEVE prevedere un loop dei messaggi. Visto che, oltre a ricevere messaggi, dobbiamo anche ridisegnare spesso il nostro schermo, modifichiamo un po’ il loop standard dei messaggi:

MSG msg;
ZeroMemory( &msg, sizeof(msg) );
while( msg.message != WM_QUIT )
{
                if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
                {
                                TranslateMessage( &msg );
                                DispatchMessage( &msg );
                }
                else
                                Render();
}



In pratica, prima controlliamo se ci sono messaggi in attesa. Se sì, eseguiamo le dovute azioni come sempre fanno i programmi Windows. Se invece nessun messaggio sta aspettando, chiamiamo la nostra funzione Render(), che eseguirà tutte le funzioni ganze che ci interessano. Non appena arriva un WM_QUIT, usciamo educatamente dal loop.

Con questa tecnica, possiamo essere sicuri che le nostre routines avranno a disposizione tutto il tempo di CPU possibile, senza interferire però col funzionamento del resto del sistema.

Vediamo adesso la funzione Render():

void Render()
{
    static int color=0;

                // Assicurati che il 3dDevice esista
    if ( g_pd3dDevice == NULL)
        return;

    // Pulisce il backbuffer con un colore noto
    g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,color), 1.0f, 0 );

    // Inizia la scena
    g_pd3dDevice->BeginScene();
   
    //
    // Qui ci metteremo il disegno della scena (nel backbuffer)
    //    

    // Finisce la scena
    g_pd3dDevice->EndScene();
   
    // Mostra la scena (il backbuffer) sullo schermo
    g_pd3dDevice->Present( NULL, NULL, NULL, NULL );

    // Cambia il colore per dare un po’ di vita
    color = (color+1) % 256;
}

I commenti dovrebbero essere sufficienti a farvi capire quello che sta succedendo (a parte la questione del backbuffer al quale riserveremo una lezione quanto prima).

Dopo aver controllato che il 3dDevice esiste, lo schermo viene riempito con un certo colore grazie al il metodo Clear(). Questa funzione ha molti argomenti perché è molto flessibile: può ripulire lo schermo, lo Z-buffer, lo stencil buffer (tutte cose che ci faranno comodo in seguito...). La macro

D3DCOLOR_XRGB( r, g, b)

serve ad esprimere un colore tramite le sue componenti rosse (r), verdi (g) e blu (b). Se vi interessano i canali Alfa di trasparenza, esiste anche D3DCOLOR_ARGBA( a, r, g, b), ma qui sto divagando...
Quindi occorre chiamare il metodo BeginScene(), che istruisce il 3dDevice a prepararsi al disegno inizializzando qualunque struttura interna di cui possa aver bisogno.

Segue quindi la fase di disegno, che noi glissiamo elegantemente, perché non sappiamo ancora come fare...
Una volta finito il disegno, occorre informare della cosa il 3dDevice, con il metodo EndScene(). Infine, vogliamo far apparire il tutto: come vedremo tra poco, tutti i nostri disegni erano finiti nel backbuffer, che per il momento è invisibile. Grazie al metodo Present() il nostro disegno appare sullo schermo come una campittura piatta. I vari argomenti di Present() servono a personalizzare questa apparizione, ma per ora non ci interessano.
L’ultima riga è un trucchetto per cambiare rapidamente il colore che viene usato per riempire la finestra.

Potete verificare che il vostro programma sta girando correttamente, perché il colore della finestra cambia molto rapidamente dal nero al blu e viceversa. Se lo schermo diventa nero per un attimo all’inizio, non preoccupatevi: è il direct3d che lo sta interrogando :-)

Un’occhiata particolare alla funzione CleanUp(), che viene chiamata all’uscita del programma:

void CleanUp()
{
    if( g_pd3dDevice)
        g_pd3dDevice->Release();

    if( g_pD3D)
        g_pD3D->Release();
}


TUTTI gli oggetti DirectX, dopo essere stati creati, vanno “rilasciati” con il metodo Release(). In seguito vedremo in dettaglio il motivo, ma per adesso ricordatevi che, una volta creato un oggetto, esso va “rilasciato” in questo modo.

Nella prossima lezione, oltre agli sfondi colorati, inizieremo a disegnare qualche oggetto. Perciò allacciate le cinture!

 

 

Torna all'indice Generale del corso di Corso di DirectX di Software Planet