Grafik zu langsam, andere Zeichenmethode gesucht

Für Fragen von Einsteigern und Programmieranfängern...
400kmh
Beiträge: 100
Registriert: Do 25. Mär 2010, 04:03

Grafik zu langsam, andere Zeichenmethode gesucht

Beitrag von 400kmh »

Wenn ich in einer Schleife vielfach in einer Sekunde die Farben von Pixeln eines großen Images.Canvas ändere, und mit "Application.Processmessages;" an den Bildschirm weitergebe, kostet das zu viel Zeit.

Es hat den Anschein, als ob jedes mal bei "Application.Processmessages;" alle Pixel des Images neu gesendet werden, auch die, die nicht geändert wurden. Außerdem scheint auch Zeit zwischen dem Löschen der alten Ausgabe und dem Zeichnen der neuen Ausgabe zu vergehen. Das Image flakert nämlich immer kurz komplet weiß auf.

Gibt es eine Möglichkeit auf direkterem Wege die Farben der Pixel des Bildschirmes zu ändern, als diese erst zwischenzuspeichern und zeitaufwändig mit "Application.Processmessages;" im Paket mit Pixeln, die garnicht verändert werden sollen, an den Bildschirm zu senden?

Optimal wäre es, wenn man mit einem Befehl direkt und augenblicklich die Farbe gewünschter Pixel verändern könnte, und alle anderen Pixel in ihrer alten Farbe bleiben würden, ohne dass sie neu geladen werden müssen.
Zuletzt geändert von 400kmh am Do 18. Nov 2010, 16:34, insgesamt 1-mal geändert.

Teekeks
Beiträge: 359
Registriert: Mi 27. Mai 2009, 20:54
OS, Lazarus, FPC: OpenSuse11.4 x86 (Lazarus: 0.9.30 FPC 2.4.2)
CPU-Target: x86
Wohnort: Cottbus

Re: Grafik zu langsam, andere Zeichenmethode gesucht

Beitrag von Teekeks »

1) Image.Doppelbuffered; nutzen.
2) zuerst auf ein nicht angezeigtes bmp zeichen.
und dann erst rüber koppieren.
3) Nur Image.repaint; nutzen und nicht Application.ProcessMessages;

oder gleich z.B. sdl nutzen, das ist dafür gemacht viel in einer Sekunde zu Zeichnen.

400kmh
Beiträge: 100
Registriert: Do 25. Mär 2010, 04:03

Re: Grafik zu langsam, andere Zeichenmethode gesucht

Beitrag von 400kmh »

Teekeks hat geschrieben:1) Image.Doppelbuffered; nutzen.
2) zuerst auf ein nicht angezeigtes bmp zeichen.
und dann erst rüber koppieren.
3) Nur Image.repaint; nutzen und nicht Application.ProcessMessages;

oder gleich z.B. sdl nutzen, das ist dafür gemacht viel in einer Sekunde zu Zeichnen.
Wie funktioniert sdl? Wie lauten die sdl-Befehle? Wo kann man das nachlesen?

Zum oberen:
Wenn ich Image.repaint benutze, ist das ganze genauso langsam. Außerdem wird nach ein paar Sekunden alles bis zur letzten Ausgabe übersprungen.
Bei Punkt 1) und 2) weiß ich ebenfalls nicht, wie das funktioniert.

Teekeks
Beiträge: 359
Registriert: Mi 27. Mai 2009, 20:54
OS, Lazarus, FPC: OpenSuse11.4 x86 (Lazarus: 0.9.30 FPC 2.4.2)
CPU-Target: x86
Wohnort: Cottbus

Re: Grafik zu langsam, andere Zeichenmethode gesucht

Beitrag von Teekeks »

Zu 1)
Das ist ganz einfach: im ObjektInspektor den Eintrag DoppelBuffered auf true setzten, dass sollte schon einmal einiges machen.

Zu 2)
Nun: zuerst erzeugst du dir eine Variable vom Typ TBitmap und zeichnest alles was du willst darauf.
Danach Kopierst du dieses Bitmap auf deine Anzeige.

Zu SDL)
Hier oder auch hier findest du Tutorials zu SDL.
Ist allerdings nicht ganz so einfach zu bedienen, aber wenn man einmal drin ist macht es total Spaß :)

felix96
Beiträge: 287
Registriert: So 29. Nov 2009, 17:44
CPU-Target: 32BitWin+64bitUbunt

Re: Grafik zu langsam, andere Zeichenmethode gesucht

Beitrag von felix96 »

Einfach nur alle 500 Schleifendurchgänge Application... machen (wenn du deinen Code so lassen willst)
Danke schonmal für eure Antworten
it´s not a bug, it´s a feature!

Euklid
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 10:38
OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
Wohnort: Hessen
Kontaktdaten:

Re: Grafik zu langsam, andere Zeichenmethode gesucht

Beitrag von Euklid »

400kmh hat geschrieben:Wenn ich in einer Schleife vielfach in einer Sekunde die Farben von Pixeln eines großen Images.Canvas ändere, und mit "Application.Processmessages;" an den Bildschirm weitergebe, kostet das zu viel Zeit.
Die Frage wird recht oft gestellt:
Du kannst Bilder sehr schnell zeichnen, wenn Du zunächst ein virutelles Bitmap erstellst (d.h. eine Variable vom Typ TBitmap), dort Deinen Zeichenvorgang abschließt (d.h. alle Pixel drauf zeichnest) und anschließend den Inhalt dieses virtuellen Bitmaps auf das TImage Deiner Form kopierst. Auf diese Weise kann ein Bild in kürzester Zeit gezeichnet werden. Noch schneller geht es dann nur noch über den direkten Zugriff auf Grafiktreiber, z.B. über OpenGL, was für Einsteiger aber wegen des Schwierigkeitsgrads kaum zu empfehlen ist.

Viele Grüße, Euklid

EDIT: Habe im Nachhinein erste gelesen, dass der Teekeks im Grunde genau diese Empfehlung schon gegeben hat.

MAC
Beiträge: 770
Registriert: Sa 21. Feb 2009, 13:46
OS, Lazarus, FPC: Windows 7 (L 1.3 Built 43666 FPC 2.6.2)
CPU-Target: 32Bit

Re: Grafik zu langsam, andere Zeichenmethode gesucht

Beitrag von MAC »

wobei zu sagen ist das die Grundlagen von OpenGl "relativ" leicht zu erlernen sind.
http://wiki.delphigl.com/index.php/Tutorial

Code: Alles auswählen

Signatur := nil;

Teekeks
Beiträge: 359
Registriert: Mi 27. Mai 2009, 20:54
OS, Lazarus, FPC: OpenSuse11.4 x86 (Lazarus: 0.9.30 FPC 2.4.2)
CPU-Target: x86
Wohnort: Cottbus

Re: Grafik zu langsam, andere Zeichenmethode gesucht

Beitrag von Teekeks »

Euklid hat geschrieben:EDIT: Habe im Nachhinein erste gelesen, dass der Teekeks im Grunde genau diese Empfehlung schon gegeben hat.
Du hast recht.
Genau das wollte ich damit sagen. :)

@MAC:
Ich komme ehrlich gesagt mit sdl einfacher klar.
Einfach ein Bild laden und drauf klatschen, bzw. die einzelnen Pixel setzten, bei OGL muss man noch immer eine Kamera einstellen usw was bei einfachen 2D-Anwendungen einfach mal overhead ist.

400kmh
Beiträge: 100
Registriert: Do 25. Mär 2010, 04:03

Re: Grafik zu langsam, andere Zeichenmethode gesucht

Beitrag von 400kmh »

Danke für die Links.
Teekeks hat geschrieben:Zu 2)
Nun: zuerst erzeugst du dir eine Variable vom Typ TBitmap und zeichnest alles was du willst darauf.
Danach Kopierst du dieses Bitmap auf deine Anzeige.
Euklid hat geschrieben:Du kannst Bilder sehr schnell zeichnen, wenn Du zunächst ein virutelles Bitmap erstellst (d.h. eine Variable vom Typ TBitmap), dort Deinen Zeichenvorgang abschließt (d.h. alle Pixel drauf zeichnest) und anschließend den Inhalt dieses virtuellen Bitmaps auf das TImage Deiner Form kopierst.
Wie funktioniert das Kopieren des Bitmaps auf die Anzeige bzw. auf ein TImage?
felix96 hat geschrieben:Einfach nur alle 500 Schleifendurchgänge Application... machen (wenn du deinen Code so lassen willst)
Dadurch würde sich die Bildschirmausgabe aber nicht mehr fließend ändern.

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Grafik zu langsam, andere Zeichenmethode gesucht

Beitrag von pluto »

Was hat in deiner Schleife eigentlich "Application.Processmessages" zu suchen? Da brauchst du in diesen Fall Überhaubt nicht. Wenn es viel zu Kurz passiert.
Und warum änderst du jede Sekunde alles? Denn Sinn erkenne ich irgendwie nicht.

Du könntest auch noch OpBitmap verwenden. Das unterstüzt ScaneLine. Wobei es gibt da auch was für canvas. Bei den Beispielen ist ein "Beispiel" dabei.
MFG
Michael Springwald

400kmh
Beiträge: 100
Registriert: Do 25. Mär 2010, 04:03

Re: Grafik zu langsam, andere Zeichenmethode gesucht

Beitrag von 400kmh »

pluto hat geschrieben:Was hat in deiner Schleife eigentlich "Application.Processmessages" zu suchen? Da brauchst du in diesen Fall Überhaubt nicht. Wenn es viel zu Kurz passiert.
Und warum änderst du jede Sekunde alles? Denn Sinn erkenne ich irgendwie nicht.
Abhängig davon, welche Tasten man drückt, soll sich die Position von Objekten verändern. Diese Objekte sollen graphisch dargestellt werden.

Daher habe ich eine Schleife erstellt, in der sehr oft in der Sekunde 1.) überprüft werden soll welche Tasten gedrückt sind, 2.) davon abhängig, die Vorgänge weiter berechnet werden und 3.) das Ganze graphisch dargestellt werden soll. Ohne "Application.Processmessages;" würde während der Schleife nichts fließend graphisch dargestellt werden, sondern erst nachdem die Schleife beendet ist, der letzte Stand graphisch dargestellt werden.

Teekeks
Beiträge: 359
Registriert: Mi 27. Mai 2009, 20:54
OS, Lazarus, FPC: OpenSuse11.4 x86 (Lazarus: 0.9.30 FPC 2.4.2)
CPU-Target: x86
Wohnort: Cottbus

Re: Grafik zu langsam, andere Zeichenmethode gesucht

Beitrag von Teekeks »

Das klingt noch mehr nach SDL, schaue es dir wirklich einmal an.
Man kann das zwar auch mit TCanvas lösen, aber auf lange Sicht gesehen ist es vl. nicht allzu Zukunftsweisend.

*Kauft SDL! Kauft SDL! Heute im Dutzend billiger* ;)

u-boot
Beiträge: 308
Registriert: Do 9. Apr 2009, 10:10
OS, Lazarus, FPC: Ubuntu 9.10 (L 0.9.28 FPC 2.2.4)
CPU-Target: 32Bit
Wohnort: 785..

Re: Grafik zu langsam, andere Zeichenmethode gesucht

Beitrag von u-boot »

400kmh hat geschrieben:Daher habe ich eine Schleife erstellt, in der sehr oft in der Sekunde 1.) überprüft werden soll welche Tasten gedrückt sind


OnKeyDown/OnKeyUp sind Events die afaik eine Schleife in diesem Fall völlig ǘberflüssig machen.
Ubuntu 9.10 (L 0.9.28 FPC 2.4.x)

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Grafik zu langsam, andere Zeichenmethode gesucht

Beitrag von pluto »

Ich nehme einfach mal an, du hast noch nicht so viel Erfahrung gesammelt. Nun weiß ich jedenfalls wo dein "Primär Problem" liegt. Dein Ansatz ist würde ich behaupten voll kommen Falsch, wenn ich ihn richtig verstanden habe.

Hier mein Vorschlag:
01: Schau dir TBitmap an
02: Schau dir Tcavnas an
03: Lade Pro Objekt ein TBitmap
04: Dieses Bitmap kannst du auf dein Canvas zeichnen und auch realtiv leicht verschieben. Hier gibt es unterschiedliche Möglichkeiten. Etwas code kann ich dir Morgen geben / zeigen.

Dir muss klar werden was ein Objekt ist. Ein Objekt ist bzw. könnte ein TBitmap sein. Wobei ein Objekt besser eine eigene Klasse ist, die Felder hat. Z.B. eins für eine Grafik, welche für die Position.
Am einfachsten ist natürlich in einem Timer alles ständig neu zu Zeichnen. Dann musst du jedoch OpenGL oder SDL nehmen.
Bei Canvas musst du anders vorgehen. Siehe unseren BreakOut Beispiel-Projekt.
MFG
Michael Springwald

Euklid
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 10:38
OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
Wohnort: Hessen
Kontaktdaten:

Re: Grafik zu langsam, andere Zeichenmethode gesucht

Beitrag von Euklid »

400kmh hat geschrieben: Wie funktioniert das Kopieren des Bitmaps auf die Anzeige bzw. auf ein TImage?
Das funktioniert z.B. mit folgendem Befehl:

Code: Alles auswählen

Image1.Canvas.Draw(0,0,VirtuelleBitmap);
Image1 ist die Image auf der Form. VirtuelleBitmap ist Deine Bitmap-Variable, die Du im "var"-Bereich definiert hast und auf die Du Deine Graphik gezeichnet hast.

Viele Grüße, Alexander

Antworten