Implementazione perfetta a V-Sync per un gioco OpenGL leggero: hai bisogno di un bocconcino di informazioni

StackOverflow https://stackoverflow.com/questions/4895085

Domanda

Nel gioco la nostra squadra assemblata di Internet sta programmando, supponiamo che tutti dal nostro pubblico abbiano il via a pieno titolo nel gioco.

Quindi, per salvare la RAM video e, si spera, dare un po 'più di tempo inattivo alla scheda grafica, usando V-Sync senza doppio buffering sarebbe la nostra opzione migliore. Quindi, in OpenGL, dobbiamo sapere come farlo.

Dalla mia comprensione, V-Sync è quando la scheda grafica viene messa in pausa una volta che viene eseguita rendendo un singolo frame fino a quando quel frame non ha finito di essere inviato al dispositivo di visualizzazione. Il doppio buffering non mettono in pausa operazioni di rendering (o forse lo fa, o forse è specifico dell'implementazione; non sono sicuro), perché invece si disegna su un secondo buffer prima di copiare sul frameBuffer, in modo che il monitor ottenga il telaio completo o no Nuovo frame (in particolare, l'ultima immagine memorizzata nel frameBuffer). Bene, non abbiamo bisogno di quella funzione, purché la scheda grafica scriva solo sul frameBuffer solo quando è necessario.

Questo è un gioco online piuttosto lento (ma è molto creativo ^_ ^). C'è pochissima azione in tempo reale. Pertanto, l'input dell'utente estremamente preciso non è una necessità; Può essere catturato dal sistema operativo come una singola unità in qualsiasi momento prima di rendere un frame.

Quindi, per fare esattamente questo, devo essere in grado di ottenere un messaggio "Frame ha finito per monitorare" da OpenGL. È possibile? In caso contrario, qual è la migliore alternativa?

Il gioco viene programmato per Windows solo al momento, ma dovrebbe funzionare per Linux in pochi mesi.

È stato utile?

Soluzione

Soffri di un malinteso su ciò che fa V-Sync. C'è una parte nella RAM video che viene continuamente inviata al dispositivo di visualizzazione a una velocità costante, la frequenza di aggiornamento del frame. Quindi, immediatamente dopo che è stato inviato un frame completo, il frame successivo viene inviato, dopo un periodo vuoto molto breve. Ma il tempo tra i frame di invio è molto più corto del tempo impiegato per inviare il frame completo.

Quello che succede senza V-Sync è che le operazioni sul contenuto del frameBuffer diventano visibili, ad esempio se il telaio è pieno alternandosi con rosso e verde e non c'è sincronizzazione V vedrai bande rosse e verdi sul monitor. Per evitare questo, V-Sync Swaps Il puntatore utilizzato dal driver di visualizzazione per accedere al frameBuffer subito dopo che è stato inviato un frame completo.

Il che ci porta a ciò che fa il doppio boffer. Senza doppio bouffering c'è poco uso per un V-Sync. L'azione attivata da V-Sync deve avvenire molto, molto velocemente. Quindi questo si riduce a scambiare un puntatore o un'operazione di blit molto veloce (potenzialmente semplicemente impostando gli attributi di mucca per la MMU della GPU).

Senza doppio bouffering e senza sincronizzazione V l'effetto è che si può vedere il processo in cui l'immagine è resa per pezzo per pezzo al frameBuffer. Naturalmente se il rendering avviene più velocemente di un periodo di frame, questo ha l'effetto che top-down vedrai un'immagine solo scarsamente popolata con sempre più contenuti visibili verso il bottem, e da qualche parte tra cui colpirà il bordo dello schermo inferiore, Wapping intorno alla cima. La linea di intersezione si muoverà.

TL; DR: basta utilizzare il doppio buffering e abilitare V-Sync per lo scambio di buffer. Non aver paura del consumo di memoria. Tutte le GPU in circolazione oggi hanno RAM più che sufficienti per fornire facilmente la memoria per i piani di colore a doppio boffer. Basta fare la matematica: 1920x1200 * RGB = 6mib, anche le GPU più piccole nei PC oggi offrono almeno 128mib di RAM. Dispositivi mobili, diciamo iPad 1024 * 768 * RGB = 2Mib vs. 32Mib per la grafica. L'interfaccia utente dell'iPad è comunque a doppio boxer.

Altri suggerimenti

Puoi usare wglGetProcAddress Per ottenere l'indirizzo di wglSwapIntervalEXT, e poi chiama wglSwapIntervalEXT(1); Per sincronizzare gli aggiornamenti con la sincronizzazione verticale. Quando lo fai, non ricevi un messaggio alla sincronizzazione verticale - glFlush Semplicemente non ritorna fino a quando non è avvenuta una retrace verticale e lo schermo è stato aggiornato. Quindi, hai un WM_PAINT gestore che assomiglia a questo:

BeginPaint
wglMakeCurrent
do drawing
glFlush
EndPaint

Il glFlush è necessario in ogni caso, per assicurarsi che il disegno che hai fatto venga inviato allo schermo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top