| Autor |
Beitrag |
Stefan S.
      
Beiträge: 184
D5
|
Verfasst: 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:
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
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 23.01.09 17:00
|
|
Stefan S. 
      
Beiträge: 184
D5
|
Verfasst: 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
      
Beiträge: 197
Ubuntu Linux
Lazarus
|
Verfasst: Fr 23.01.09 18:01
1. Bei Flimmern von GDI-Objekten ist die erste Allgemeinmedizin immer erstmal
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
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 23.01.09 18:39
Einloggen, um Attachments anzusehen!
|
|
Stefan S. 
      
Beiträge: 184
D5
|
Verfasst: 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
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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. 
      
Beiträge: 184
D5
|
Verfasst: 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.
|
|
|