PDA

View Full Version : problema refresh OpenGL in finestre windows


Black imp
08-07-2006, 04:39
sto programmando una piccola applicazione grafica, un piccolissimo motore grafico - chiamiamolo così :mc: - utilizzando le finestre di windows e la libreria windows.h . ogni volta che apro un menu della finestra smette di aggiornare il rendering, tanto che se per es. apro tramite il menu la finestra di browsing per selezionare un file e la muovo, sotto l'immagine rimane tutta impressa con la finestra di browsing. c'è un'opzione da qualche parte per comunicare che la finestra non deve bloccare il rendering?

seconda cosa: come si attiva il double buffering quando si crea come in questo caso un contesto per opengl?

grazie :)

Andlea
08-07-2006, 09:38
Usando il double buffer il problema dovrebbe risolversi per i menu, per quanto riguarda il file dialog basta chiamare
Invalidate(true);
UpdateWindow();


Per abilitare il double buffering con wgl devi usare questo pfd

static PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
1, // version number
PFD_DRAW_TO_WINDOW | // support window
PFD_SUPPORT_OPENGL | // support OpenGL
PFD_DOUBLEBUFFER, // double buffered
PFD_TYPE_RGBA, // RGBA type
24, // 24-bit color depth
0, 0, 0, 0, 0, 0, // color bits ignored
0, // no alpha buffer
0, // shift bit ignored
0, // no accumulation buffer
0, 0, 0, 0, // accum bits ignored
32, // 32-bit z-buffer STENCIL
0, // no stencil buffer
0, // no auxiliary buffer
PFD_MAIN_PLANE, // main layer
0, // reserved
0, 0, 0 // layer masks ignored
};

Nel rendering
void CMFC_GLView::OnDraw(CDC* pDC){

....

SwapBuffers(pDC->m_hDC);


Se hai altri dubbi sono qui

Black imp
08-07-2006, 13:36
grazie mille. adesso leggo bene. tieni conto però che non posso usare le mfc.


[EDIT]

ho cercato nell'help index e ho letto il codice ma in effetti mi sembra che tu stia usando comandi delle mfc che non posso usare perchè ormai ho costruito tutta l'applicazione con le windows.h che non sono compatibili. :mc:


spiego meglio il problema del rendering: appena anche solo premo alt per evidenziare i menu il rendering si ferma. se poi apro appunto la finestra per esplorare i file e la muovo rimane impressa. quando poi la chiudo il rendering riparte senza problemi e pulisce ma il problema è che non volevo si fermasse proprio.

Andlea
08-07-2006, 14:37
si, quello che ho postato è usato nelle mfc, ma il codice si adatta con un paio di cambiamenti
In ogni caso puoi usare il basecode di NeHe
http://nehe.gamedev.net/counter.asp?file=files/basecode/nehegl_net.zip
Questo è il kernel wgl

Black imp
08-07-2006, 15:03
si, quello che ho postato è usato nelle mfc, ma il codice si adatta con un paio di cambiamenti
In ogni caso puoi usare il basecode di NeHe
http://nehe.gamedev.net/counter.asp?file=files/basecode/nehegl_net.zip
Questo è il kernel wgl


ti ringrazio sono partito proprio da lì ma non facendo lui uso di menu non si pone neanche il problema. tratta l'aspetto windows quel tanto che gli basta per il rendering. tra l'altro anche solo spostando la finestra il rendering si blocca :rolleyes:

vedremo. grazie lo stesso

Andlea
09-07-2006, 10:27
si, il basecode era solo per farti vedere come creare il context con il double buffer.
Per la questione del rendering ora non mi viene in mente nulla, di solito uso mfc e non ho questi problemi.
Prima ditutto, dove fai la chiamata al render callback? insomma, quando aggiorni l'immagine?
on idle?
IN caso affermativo invece di usare onidle, prova a settare un timer e gestire il refresh dell'immagine nell'evento WM_TIMER
Qualcosa del genere

void OnTimer(UINT nIDEvent)
{
Invalidate(true);
UpdateWindow();
CView::OnTimer(nIDEvent);
}

void OnInitialUpdate(){
CView::OnInitialUpdate();
SetTimer(1, 10, 0);
}

Questo è in mfc, ma adattarlo a win32 dovrebbe essere banale

Black imp
09-07-2006, 13:33
mmmh interessante grazie. in effetti disegna l'immagine quando non ci sono messaggi pendenti:


if (!InitWindow("OpenGL Framework",WIDTH,HEIGHT,BITS,fullscreen))
{
return 0; // Quit If Window Was Not Created
}


while(!done) // Loop That Runs While done=FALSE
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) // Is There A Message Waiting? - non blocking!
{
if (msg.message==WM_QUIT) // Have We Received A Quit Message?
{
done=TRUE; // If So done=TRUE
}
else // If Not, Deal With Window Messages
{
TranslateMessage(&msg); // Translate The Message
DispatchMessage(&msg); // Dispatch The Message
}
}
else // If There Are No Messages
{
// Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene()
if (active) // Program Active?
{
if (keys[VK_ESCAPE]) // Was ESC Pressed?
{
done=TRUE; // ESC Signalled A Quit
}
else if (keys[VK_LEFT])
{
IncAngle(ANGLE_Y,DEFAULT_ANGLE_INC);
keys[VK_LEFT]=false;

}
else if (keys[VK_RIGHT])
{
IncAngle(ANGLE_Y,-DEFAULT_ANGLE_INC);
keys[VK_RIGHT]=false;
}
else if (keys[VK_UP])
{

IncAngle(ANGLE_X,-DEFAULT_ANGLE_INC);
keys[VK_UP]=false;
}
else if (keys[VK_DOWN])
{
IncAngle(ANGLE_X,DEFAULT_ANGLE_INC);
keys[VK_DOWN]=false;
}
else if (keys['Q'])
{
IncAxis(AXIS_Z,DEFAULT_AXIS_INC);
keys['Q']=false;
}
else if (keys['A'])
{
IncAxis(AXIS_Z,-DEFAULT_AXIS_INC);
keys['A']=false;
}
else if (keys['Z'])
{
IncAxis(AXIS_X,+DEFAULT_AXIS_INC);
keys['Z']=false;
}
else if (keys['X'])
{
IncAxis(AXIS_X,-DEFAULT_AXIS_INC);
keys['X']=false;
}
else // Not Time To Quit, Update Screen
{
PaintCanvas(); // Draw The Scene
SwapBuffers(hDC); // Swap Buffers (Double Buffering)
}
}


Qui in fondo chiama PaintCanvas, che è la funzione di rendering, quando non ha altro da fare. Però i messaggi pendenti li rilancia quindi non capisco bene.

Tra l'altro mi sono accorto che stavo già utilizzando il double buffering ! :p

Andlea
10-07-2006, 11:24
Si è normale che così il rendering si blocchi
All'init della finestra fai partire un timer con SetTimer
Poi gestisci il messaggio WM_TIMER con PrintCanvas
Qui trovi la documentazione per il timer:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/timers/timerreference/timerfunctions/settimer.asp

Black imp
10-07-2006, 12:53
Si è normale che così il rendering si blocchi
All'init della finestra fai partire un timer con SetTimer
Poi gestisci il messaggio WM_TIMER con PrintCanvas
Qui trovi la documentazione per il timer:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/timers/timerreference/timerfunctions/settimer.asp



grazie mille ! adesso provo. ti do un altra indicazione: quando apro dei messagebox non si blocca il rendering. non vorrei fosse solo un setting che non do ai menu o alla finestra stessa sulla priorità.
mi sto chiedendo però che cosa succede se il timer lo setto a un tempo inferiore a quello che ci impiega il sistema a disegnare il frame... e se il timer scatta mentre la funzione di paint è giustamente bloccata perchè sto accedendo alle strutture con semaforo che servono per memorizzare la posizione del robot che muovo? o viceversa se lo setto troppo alto... su qualsiasi pc fa lo stesso numero di frame allora?
boh vabbeh intanto provo. ti ringrazio ancora. :D :D

Andlea
10-07-2006, 13:07
Il messagebox una volta lanciato lascia passare i messaggi.
Il timer puoi impostarlo a 1ms, poi ovviamente il messaggio verra dispatchato appena il sistema riesce. Ovviamente ci sarà una differenza a seconda delle risorse libere sul pc, ma questo è del tutto normale ed inevitabile.
Se vuoi ti posto l'eseguibile di un mio programmino, n sistemi particellari, estensione dell'esempio di Nehe, dove con il timer aggiorno la posizione delle particelle e chaimo il renderer.
Aprendo menu o spsostando la finestra(questo lo mette a dura prova per via del numero di particelle) il rendering continua

Black imp
11-07-2006, 13:32
Il messagebox una volta lanciato lascia passare i messaggi.
Il timer puoi impostarlo a 1ms, poi ovviamente il messaggio verra dispatchato appena il sistema riesce. Ovviamente ci sarà una differenza a seconda delle risorse libere sul pc, ma questo è del tutto normale ed inevitabile.
Se vuoi ti posto l'eseguibile di un mio programmino, n sistemi particellari, estensione dell'esempio di Nehe, dove con il timer aggiorno la posizione delle particelle e chaimo il renderer.
Aprendo menu o spsostando la finestra(questo lo mette a dura prova per via del numero di particelle) il rendering continua


ah bello quel tutorial, quello delle particelle. mi sono stampato tempo fa tutto nehe e ho tirato giù tutto il codice anche se si vede che non è un esperto programmatore è moooolto utile il suo lavoro. ormai ho capito come si fa però dai posta, credo che sia interessante anche per altri. :)

Andlea
11-07-2006, 14:02
http://www.megaupload.com/?d=HNSYDRN3
La gestione dei movimenti è presa da nehe, per il resto ho suddiviso in 3 classi, la particella, il sistema particellare che contiene le particelle, e il particle manager che contiene un vettore di sistemi particellari.

Black imp
12-07-2006, 05:14
Grandissimo! ehm non ho letto il sito anche perchè mi linka una pagina generale :mc: ... però ho provato prima a gestire WM_PAINT e anche se il rendering continuava, tuttavia non riuscivo più ad aprire le messagebox in modo normale: appena selezionavo una entry del menu che doveva far comparire una messagebox la finestra diventava inattiva, renderizzava intanto però non si poteva più fare altro e non compariva nessuna messagebox... poi schiacciando ALT compariva. premuto OK la finestra tornava attiva. poi ho provato il timer come dicevi tu, inizializzato nella funzione principale della finestra con l'ultimo parametro NULL così lo gestisce la callback sotto WM_TIMER. perfetto!!! grazie mille! ora posso dormire tranquillo - sarò più tranquillo quando tra qualche giorno mi leverò questa palla al piede che è l'ultimo scoglio prima della tesi dopo innumerevoli anni :cry:

grazie ancora!! :oink:

Andlea
12-07-2006, 09:38
Prego :)

Il link funziona però, evi aprirlo poi in alto a dx immettere le lettere proposte, così puoi scaricare il file
spe, lo allego qua

Black imp
12-07-2006, 12:03
salvato! torno a dormire poi lo guardo. devo recuperare o muoio :O

:D