FillRect() und BitBlt() - flackern?



  • Rhombicosidodecahedron schrieb:

    OpenGL

    Das werde ich (irgendwann) mal versuchen! Dummerweise zeichne ich grade viel mit einzelnen Pixeln (Fraktale), daher schien mir OpenGL eigentlich kein guter Ansatz zu sein (ein Lehrbuch dazu habe ich aber schon).

    Hier, hab deine Brüder und deine Schwestern gefunden gefunden:
    http://thesaurus.maths.org/mmkb/gallery.html?folder=live3D

    😉



  • NickHappy schrieb:

    Probiere mal folgendes:
    Setze nXDest, nXDest, nXSrc, nYSrc auf 0. Mach deinen BackBuffer genauso gross wie den ScreenDC.
    Hatte mal das selbe Problem. BitBlt wurde langsam, als ich mit offsets rumhantiert habe.

    Das hat leider nichts gebracht, flackert wie ehedem - und dann auch, wenn das Fraktal klein ist (nur nicht so auffällig unser Auge scheint da verwirrt zu sein). 😉



  • Hast du das mal konkret überprüft ob es wirklich die BitBlt()-Funktion ist die da bremst ?
    Wenn Du ne DIB benutzt, könntest du dir evtl. noch DrawDib() angucken...
    Hinter InvalidateRect() würde ich sicherheitshalber noch ein UpdateWindow() packen...



  • Hast du das mal konkret überprüft ob es wirklich die BitBlt()-Funktion ist die da bremst

    ➡ Ich hab bevor meine Direct3D-Zeiten begonnen haben, angefangen ein RPG zu programmieren; und zwar komplett mit BitBlt + Doublebuffering...
    Die Geschwindigkeit von BitBlt() war dabei schon ein Problem ...weil es echt "radikal" geflacktert hat...
    Kann echt nur DirectX bzw. OpenGL...oder eine andere GrafikLib empfehlen...
    Aber....:
    Ich hatte damals 1024x768 als Bildschirmauflösung und hab das Flackern "bekämpft" in dem ich den Bildschirm in Bereiche unterteilt und einzeln abgearbeitet habe...
    Dadurch wurde das Programm/BitBlt schneller...Was zwar irgendwie ein Widerspruch ist aber trotzdem funktioniert hat...

    MfG Kuldren



  • Also, da mir DirectDraw schon immer zu hoch war, hab ich in den letzten Jahren meine Spiele und andere Grafikprogramme mit SetDIBitsToDevice sichtbar gemacht.
    Egal wie viele fps du einstellst und wie langsam der Computer ist, da flackert nichts.



  • Ich meine die WM_TIMER UND WM_PAINT Nachrichten sind beides Messages die nicht an das Ende der Message-Queue gepackt werden sondern bevorzugt verarbeitet werden.
    Nun könnte es sein, je nachdem wieviele Timer und mit welchem Timeout die Timer laufen, dass die WM_TIMER-Messages die WM_PAINT-Messages quasi verzögern. Ein UpdateWindow() hinter InvalidateRect() würde zumindest sicherstellen, dass WM_PAINT direkt verarbeitet wird.



  • Nanyuki schrieb:

    Also, da mir DirectDraw schon immer zu hoch war, hab ich in den letzten Jahren meine Spiele und andere Grafikprogramme mit SetDIBitsToDevice sichtbar gemacht.

    msdn meint:

    To repeatedly redraw a bitmap in a window, however, the application should use the BitBlt function. For example, a multimedia application that combines animated graphics with sound would benefit from calling the BitBlt function because it executes faster than SetDIBitsToDevice.

    Naja, ich hab bisher eigentlich auch SetDIBitsToDevice() für schneller gehalten 😉
    Müsste man mal benchen 😉



  • geeky schrieb:

    Ich meine die WM_TIMER UND WM_PAINT Nachrichten sind beides Messages die nicht an das Ende der Message-Queue gepackt werden sondern bevorzugt verarbeitet werden.
    Nun könnte es sein, je nachdem wieviele Timer und mit welchem Timeout die Timer laufen, dass die WM_TIMER-Messages die WM_PAINT-Messages quasi verzögern. Ein UpdateWindow() hinter InvalidateRect() würde zumindest sicherstellen, dass WM_PAINT direkt verarbeitet wird.

    Mmh, ja in diese Richtung hatte ich auch schon gedacht, aber ich stoppe den betreffenden Timer, führe meine Berechnungen aus (die in eine DIBSection Bildpunkte schreiben) und und rufe dann mit UpdateWindow() WM_PAINT auf wo ich dann als einzige Zeichenoperation eien BitBlt mache.

    case WM_TIMER:
    
    	switch (wParam) { 
    
    		case IDT_TIMER1:
    
    			KillTimer(hWnd, IDT_TIMER1);
    
            			// maximale Ausdehnung holen
    			(.. schnipp ..)
    
    			// Alles was zuvor gezeichnet wurde löschen
    			(.. schnipp ..)
    
    			// Punkte des aktuellen Frames berechnen und zeichnen
    			(.. schnipp ..)
    
    			//WM_PAINT aufrufen
    			InvalidateRect(hWnd, &rect, false);
    			UpdateWindow(hWnd);
    
    			(.. schnipp ..)
    
    			SetTimer(hWnd, IDT_TIMER1, delay_IDT1, NULL);
    
    		return 0;
    
    (.. ganz viel Schnipp ..)
    
    case WM_PAINT:
    	GdiFlush();
    	myDevCon = BeginPaint(hWnd, &ps);
    	BitBlt(	myDevCon,
    		xmin, ymin,
    		xmax+1, ymax+1,
    		myBackBuffer,
    		xmin,ymin,
    		SRCCOPY);
    	EndPaint(hWnd, &ps);
    return 0;
    

    Wenn ich das richtig verstehe, läuft der Timer doch erst wieder an, nach dem UpdateWindow() durchgeführt ist, das Programm also aus WM_PAINT zurückkehrt? Oder, wie?
    Ich verstehe wirklich nicht warum das flackert? Herrjeh!



  • Wie lange braucht BitBlt() denn bei dir ?



  • geeky schrieb:

    Wie lange braucht BitBlt() denn bei dir ?

    Keine Ahnung! Ich habe einmal vorher GetTickCount() und einmal hinterher aufgerufen, die Differenz war IMMER 0, daher gehe ich davon aus, dass BitBlt < 1.0 ms arbeitet. Das dürfte keinesfall flackern!

    Mannomann, woher kommt das dann? 😕

    Wer möchte kann ja mal selbst gucken: http://ticore.de/share/ifs.zip

    Es fängt immer an zu flackern, wenn das Fraktal größer als etwa 60-70% des Bildschirms einnimmt.



  • Dein Bildschirmschoner stürzt ab bevor man etwas sieht.



  • Mit welcher Meldung?



  • Mit Problembericht senden. 🤡



  • Bei mir läufts flüssig 😉



  • Hast Du in der WNDCLASS-Struktur bei Erzeugung der Fensterklasse einen "background brush" angegeben? Falls ja: in diesem Fall füllt das System vor jedem WM_PAINT den ungültigen Fensterbereich mit der Hintergrundfarbe, was natürlich "Flackern" bewirkt.



  • Einige kleine Änderungen:

    • Nicht immer neu
    SetTimer und
    Killtimer
    

    verwenden

    • Vielleicht feste Fensterbreite einbauen
    • Etwas noch an der WindowPRoc ändern
    case WM_TIMER:
    /* Irgendetwas */
    //break /* Kein Break sonst flimmer */
    // Damit man keine Nachricht senden muss
    case WM_PAINT:
    /* Irgendetwas */
    break;
    case WM_ERASEBKGND: return false; // Wichtig ! - Sonst flimmer!
    
    • Fertige "dingse"-Anzeiger gibt's doch wie Sand am Bodensee

    So, ach ja:

    timmix schrieb:

    Rhombicosidodecahedron schrieb:

    OpenGL

    Das werde ich (irgendwann) mal versuchen! Dummerweise zeichne ich grade viel mit einzelnen Pixeln (Fraktale), daher schien mir OpenGL eigentlich kein guter Ansatz zu sein (ein Lehrbuch dazu habe ich aber schon).

    Hier, hab deine Brüder und deine Schwestern gefunden gefunden:
    http://thesaurus.maths.org/mmkb/gallery.html?folder=live3D

    😉

    Ohhhh, wie schön meine ganze Familie ... so groß ... ich könnte heulen ... *heul* * heul* ... ah - da der alte Tedraeder - immer noch da ... und ...

    Mit freundlichen Grüßen und nicht ganz (garnicht) ehrich gewesend
    Rhombicosidodecahedron


Anmelden zum Antworten