PDA

Visualizza la versione completa : [C] Uso del double buffering per evitare sfarfallio con GDI


giorgio_kollias
06-08-2012, 23:21
Salve a tutti, ho creato un semplice programma utilizzando le GDI di windows che muove a ripetizione una bitmap in modo da sembrare che scrolli, solo che c' molto sfarfallio. Ho cercato un po' sul web ed uscito questo "doppio buffering", ma so poco e nulla su cosa sia e assolutamente nulla su come si usi utilizzando le GDI API (programmo in C). Potreste spiegarmi come utilizzarlo?
Grazie mille.

giorgio_kollias
07-08-2012, 14:12
Nessuno?

XAlbeX
08-08-2012, 01:48
Da quel che so GDI non pensato per disegnare frames su frames. Il disegno istantaneo, cio appena tu dai il comando lui comincia a disegnare sulla memoria "visibile", per questo ha problemi come lo sfarfallio o il tearing.

Per risolvere il tearing devi attivare il v-sync (non so se possibile con GDI)
Per lo sfarfallio prova ad evitare di ridisegnare lo sfondo, piazzaci sopra la bitmap direttamente e pulisci poi quello che rimane dell'immagine precedente.

Se invece vuoi usare il double buffering crei una superficie non visibile e ci disegni dentro le cose e poi la copi sulla superficie visibile.

giorgio_kollias
08-08-2012, 19:25
Evitando di ridisegnare lo sfondo si vede comunque un po' "a scatti", comunque cercando un po' sul web ho visto che esiste il doppio buffering per le GDI, ma non ho capito come usarlo... Il codice questo:


// Nel WinMain

SetTimer(hwnd,101,1,Scroll);

//Nella WindowProcedure

case WM_PAINT:
wDC = BeginPaint(hwnd, &wps);
hMemDC = CreateCompatibleDC(wDC);
SelectObject(hMemDC, BitBackG);
GetObject(BitBackG, sizeof(bm), &bm);
Width=bm.bmWidth+(WLimits.bottom-bm.bmHeight);
if(Width<WLimits.right) Width=WLimits.right;
StretchBlt(wDC, BackGx, 0, Width, WLimits.bottom, hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
StretchBlt(wDC, BackGx+Width, 0, Width, WLimits.bottom, hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
DeleteDC(hMemDC);
EndPaint(hwnd, &wps);
break;

// Funzione Scroll

BackGx-=5;
if(BackGx<-Width) BackGx=0;
InvalidateRect(hwnd, &WLimits, TRUE);
UpdateWindow(hwnd);


come si pu trasformare in modo che funzioni con il boppio buffering?

XAlbeX
09-08-2012, 21:42
Basta creare una bitmap di dimensioni uguali alla finestra e disegnare su di essa il frame. Poi copi il frame finito nella finestra.

Ma non risolverai il problema. Il double buffering utile quando hai bisogno di cancellare tutta la superficie prima di ridisegnare. Se operi per "rimpiazzo" (i pixel non vengono cambiati pi volte nello stesso frame) non ne hai bisogno, e l'unico effetto che otterrai in pi sar il consumo di risorse.


Evitando di ridisegnare lo sfondo si vede comunque un po' "a scatti"
Questo probabilmente dovuto alla mancanza del v-sync.

Loading