Autor Beitrag
Stefan S.
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 184


D5
BeitragVerfasst: Fr 23.01.09 16:14 
Ich bewege in einem Projekt mit OpenGL ein Objekt im dreidimensionalen Raum und zeige unter anderem seine Welt- und Bildschirmkoordinaten sowie die Gesamt-Modelviewmatrix an. Diese ändern sich dabei natürlich sehr häufig, je nachdem in was für Zeitabständen die Werte der Transformations-Befehle in der Rendering-Schleife geändert werden. Bei meiner Methode, die Daten anzuzeigen, flimmert es, wenn die Zeitabstände zu kurz sind, komischerweise jedoch nur bei der Anzeige der Matrix. Die hat ein eigenes TImage, die Methode ist aber eigentlich die selbe wie bei den Koordinaten... Ich kann allerdings schlecht in der Schleife nur einzelne Elemente der Matrix aktualisieren, weil z.B. bei komplizierteren Rotationen eh fast alle Elemente betroffen sind.

Zuerst hatte ich die Werte mit TextOut in einer Paintbox ausgegeben. Ich hab aber hier im Forum gelesen, dass man Paintboxen nur über das Ereignis OnPaint füllen sollte, was bei meiner Rendering-Schleife natürlich ungünstig ist. Deswegen bin ich auf ein TImage umgestiegen, was aber in Sachen Flimmern höchstens eine geringfügige Verbesserung war. Auch das Einschalten von "DoubleBuffered" oder die Methode, den Text erst in den Canvas eines TBitmap zu schreiben und dann mit BitBlt auf das TImage zu kopieren, brachte keine Verbesserung. Neben dem Flimmern hab ich noch das Problem, dass der Text stehen bleibt, was man zum Beispiel dann sieht, wenn eine positive Zahl direkt nach einer negativen anzeigt wird (das Minus bleibt dann stehen). In der Schleife ständig Repaint auszuführen kann aber auch nicht der richtige Weg sein, dadurch wird ja das Flimmern nochmal verstärkt.

Ich hab mal ein bisschen mit der Forensuche rumgesucht, wie man so etwas normalerweise löst, bin aber nicht wirklich auf eine "Musterlösung" gestoßen. Wie gibt man am besten Werte aus, die sich häufig ändern, ohne dass es flimmert? Ist es am Ende sogar praktischer, mit Arrays von Labels zu arbeiten, wo ich eigentlich extra auf Paintbox/TImage umgestiegen bin, weil ich das für unsauber hielt?

Hier noch der Code zum Anzeigen der Gesamt-Modelviewmatrix:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
  with imgMatrixAnzeige.Canvas do
   begin
    Canvas.Brush.Style := bsClear;
    with Font do
     begin
      Name := 'Arial';
      Size := 12;
     end;
    for i := 1 to 4 do
      for j := 1 to 4 do
       begin
        PaintText := Float_Ausgabe(Anzeige_Matrix[(i-1)*4+(j-1)]);
        TextKoordinaten.x := 20+(i-1)*72;
        if Anzeige_Matrix[(i-1)*4+(j-1)] < 0 then
          TextKoordinaten.x := TextKoordinaten.x - TextWidth('-');
        TextKoordinaten.y := 10+(j-1)*26;
        TextOut(TextKoordinaten.x,TextKoordinaten.y,PaintText);
       end;
   end;
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19346
Erhaltene Danke: 1754

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 23.01.09 17:00 
user profile iconStefan S. hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden Delphi-Quelltext
1:
2:
3:
  with imgMatrixAnzeige.Canvas do
   begin
    Canvas.Brush.Style := bsClear;
Dass du nicht den Brush deines Images sondern den deines Formulars änderst ist dir hoffentlich klar...

Ein Flackern konnte ich bei mir so erstmal nicht reproduzieren, wenn ich eine TPaintBox mit Hintergrundbitmap benutze. Ich muss mal eine kleine Demo mit mehr Werten basteln, um das richtig zu testen. ;-)
Stefan S. Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 184


D5
BeitragVerfasst: Fr 23.01.09 17:32 
Nein, das war mir nicht klar, das war nämlich ein Leichtsinnsfehler. ^^
Jetzt bleiben natürlich immer die vorigen Werte stehen, dadurch ergibt sich mit der Zeit ein unleserliches "Textknäuel". Da ist ja neben der Frage, wie ich das Flimmern verhindere, immer noch die, wie ich am besten die alten Werte überschreibe. ^^ Soll ich einfach ein Rechteck der Hintergrundfarbe drüberzeichnen?
Maweki
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 197

Ubuntu Linux
Lazarus
BeitragVerfasst: Fr 23.01.09 18:01 
1. Bei Flimmern von GDI-Objekten ist die erste Allgemeinmedizin immer erstmal
ausblenden Delphi-Quelltext
1:
Form1.DoubleBuffered := true;					


2.
Ja, einfach mit nem entsprechendfarbigem Rechteck überzeichnen. Wenn du weiter dort nix draufmalst, könnte Clear (oder ist das bei Canvas Clean?) schneller sein.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19346
Erhaltene Danke: 1754

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 23.01.09 18:39 
user profile iconMaweki hat folgendes geschrieben Zum zitierten Posting springen:
1. Bei Flimmern von GDI-Objekten ist die erste Allgemeinmedizin immer erstmal
ausblenden Delphi-Quelltext
1:
Form1.DoubleBuffered := true;					
Hat er ja schon gemacht. ;-)
user profile iconStefan S. hat folgendes geschrieben Zum zitierten Posting springen:
Auch das Einschalten von "DoubleBuffered" oder...


user profile iconStefan S. hat folgendes geschrieben Zum zitierten Posting springen:
Nein, das war mir nicht klar, das war nämlich ein Leichtsinnsfehler. ^^
Wie so oft, wenn jemand meint mit with die "Übersicht" (und meistens die Fehlerquote gleich mit) steigern zu müssen. ;-)

Ich habe in den Anhang mal eine Demo gelegt, da habe ich einen Timer auf 1 (so schnell geht der nicht wirklich, ich weiß) gesetzt und ändere ständig Werte, aber ein Flimmern kann ich nicht erkennnen. :nixweiss:
Einloggen, um Attachments anzusehen!
Stefan S. Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 184


D5
BeitragVerfasst: Fr 23.01.09 19:56 
Das Testprogramm flimmert tatsächlich auch bei mir nicht. Sogar wenn ich das Timer-Ereignis so abändere, dass jeder Wert bei jedem Durchlauf geändert wird. Sehr merkwürdig, im Prinzip mach ich ja nichts anders. Ich hab es jetzt auch noch mal so geändert, dass bei mir ebenfalls die Werte nebenbei in ein TBitmap gezeichnet und bei OnPaint mit BitBlt gezeichnet werden. Damit flackert die Paintbox bei sehr hoher Frequenz nicht mehr so, dass man für Sekundenbruchteile die graue Arbeitsfläche dahinter sieht, aber so wie das TImage flimmert es immer noch.

Kann es denn am Drumherum liegen? Hat es einen Einfluss, dass ich in der Schleife deutlich mehr Code durchlaufe als in dem Testprogramm, oder dass ich auch OpenGL verwende? Ich kann mir sonst wirklich nicht erklären, warum es hier flimmert und da nicht...
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19346
Erhaltene Danke: 1754

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 23.01.09 20:11 
Du könntest dein Programm ja mal komplett kopieren und dann alles unwichtige, was damit nicht direkt zu tun hat, rauslöschen. Wenn das dann immer noch auftritt, könntest du das verkleinerte Programm dann posten (also mit Quelltext), damit ichs direkt dort sehen (und testen) kann.

(Du kannst es auch per PN schicken, wenn du es nicht öffentlich posten möchtest.)
Stefan S. Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 184


D5
BeitragVerfasst: Fr 23.01.09 23:44 
Nach einigem Rumprobieren hab ich des Rätsels Lösung. Das TImage bzw. die Paintbox ist in einer TGroupBox platziert. Bei der muss ich nochmal extra DoubleBuffered auf "true" setzen, dann flimmert nichts mehr. Ich bin darauf gekommen, weil es in einem TImage, das einfach nur so auf dem Formular platziert war, keine Flimmer-Probleme gab.
Ich benutze jetzt übrigens die Image-Komponente, weil da alles einmal gezeichnete so schön bestehen bleibt und mir die Paintbox mit OnPaint-Ereignis in dem Fall keine Vorteile bringt.

Vielen Dank für die Hilfe. Problem gelöst und wieder was gelernt.