DEUTSCHE VERSION |
|
Links | | | Forums | | | Comments | | | Report news |
Chat | | | Polls | | | Newsticker | | | Archive |
amiga-news.de Forum > Programmierung > Grafik Geschwindigkeit | [ - Search - New posts - Register - Login - ] |
-1- | [ - Post reply - ] |
2004-07-21, 08:20 h Reth Posts: 1858 User |
Hallo allerseits, ich habe mir ein ziemliches Problem aufeghalst, für das ich einige clevere Tipps brauchen könnte. Bei meinem Programm sieht das Ganze wie folgt aus: Ich habe Animationsobjekte, die in einer Liste liegen. Pro Zeiteinheit wird diese Liste durchlaufen und jedes Objekt gefragt, ob es neu gezeichnet werden muss. Wenn das der Fall ist wird mit diesem Objekte gegen alle anderen Objekte geprüft, ob sie das neu zu zeichnende überdecken (fürs Clipping, da jedes Objekt vor dem Zeichnen seinen Hintergrund sichert, um ihn ggf. wieder herstellen zu können). D.h. die Liste wird nochmal durchlaufen, wobei ich den Objekten eine Tiefenstaffelung gegeben habe, so dass nicht alle geprüft werden müssen. Jedes Animationsobjekt kann aus unterschiedlich vielen Frames bestehen, die eine Animation erzeugen (darum wird pro Zeiteinheit geprüft, welches Objekt neu gezeichnet werden muss, da die Animationen ja unterschiedlich ablaufen und einige z.T. schon beendet sind und nur noch als statisches Bild vorhanden sind). Vom Aussehen her gleiche Animationsobjekte (also Objekte mit den gleichen Grafiken) haben immer die gleiche Framezahl und auch identische Animationsparameter. Das Ganze hab ich in C++ implementiert mit Hilfe der BltMaskBitMap-Funktionen. Jedes Objekt bekommt eine Bitmap für seinen Hintergrund beim Initialisieren. Die eigentlichen Grafiken liegen nur einmal im Speicher und werden teilweise von unterschiedlichen Objekten verwendet. Nun ist das Ganze aber bei ca. 200 Objekten viel zu langsam. Hat denn jemand ne gute Idee, wie man das Ganze optimieren kann? (Assembler scheidet aus, da ich das Ganze in C++ belassen möchte, um es ggf. leichter portieren zu können). Ich kann mir denken, dass das Ganze ohne Codeausschnitte nur schwer zu beantworten ist, aber evtl. hat jemand grundlegende Ideen zur Verbesserung? Ich hab in meinem Programm das Listenprinzip mit abzulaufenden Objekten an allen Ecken und Enden eingebaut (einfach verkettete Listen, die mit Hilfe von for-Schleifen abgelaufen werden), schätze das macht das Ganze so lahm. Vielen Dank schon mal! Ciao [ - Answer - Quote - Direct link - ] |
2004-07-21, 10:54 h whose Posts: 2156 User |
Zitat: Du kannst Dir diese zweite Überprüfung sparen. Da Du eine Überdeckungspriorität ja schon "eingebaut" hast, ist die Sicherung des Hintergrundes spätestens bei einem weiteren Objekt, das eins mit niedrigester Priorität überdeckt, nicht mehr von so großer Bedeutung, sofern Du die Objekte in jedem "Frame" neu zeichnen läßt. Beim Zurückschreiben des gesicherten Hintergrundes solltest Du aber darauf achten, daß die Reihenfolge dann umgekehrt zu der des Neuzeichnens der Objekte ist, d.h. das "oberste" Objekt schreibt den gesicherten Hintergund zuerst wieder ins Bild. In diesem Fall stellt sich alles von ganz allein "korrekt" wieder her Grüße [ - Answer - Quote - Direct link - ] |
2004-07-21, 11:15 h whose Posts: 2156 User |
Hab noch was vergessen: Wenn Du die Listen optimal planst, ist es auf keinen Fall lahm wegen der Listen. Das Listen-Prinzip wurde schon anno dunnemals bei PC-Spielen mit Software-Sprites verwendet, unter anderem, weils einem einen sehr zügigen Bildaufbau ermöglicht (und noch ein paar andere Sachen mehr). In meiner Artikelserie in der AmigaInsider kommt das auch zur Sprache, leider noch nicht in der in Kürze erscheinenden Ausgabe sondern erst später. Kannst mir zu dem Thema ja mailen, wenn Du noch Fragen hast. Grüße [ - Answer - Quote - Direct link - ] |
2004-07-21, 11:30 h Reth Posts: 1858 User |
Hi, also die Listen sind von mir programmierte einfach verkettete Listen (hab ne Templateklasse gebaut, die das kann), hoffe das kam so rüber!? Ich sag das Ganze nur, weil ich denke, dass es beim AmigaOS auch vom System her Listen für Grafiken gibt (bin mir grad nicht mehr sicher). Also die Überdeckungsneuzeichnung wird nur aktiv, wenn sich ein Objekt ändert, dass von einem anderen momentan überdeckt wird. Dann wird nach dem Neuzeichnen, des überdeckten Objektes das darüberliegende dazu gebracht, seinen Hintergrund zu aktualisieren. Das Ganze würde aber entfallen, wenn man es so implementiert, wie Du es beschrieben hast. Bin sehr an weiteren Infos/Hilfen interessiert. Meine Mail ist Rene.Thol(AT)gmx.de. Danke Ciao [ - Answer - Quote - Direct link - ] |
2004-07-21, 11:43 h whose Posts: 2156 User |
Zitat: Yep, ich hatte das jedenfalls so angenommen. Wäre auch die (vordergründig) einfachste Lösung. Sinnvoller wäre es aber, diese Liste je nach Bedarf in beiden Richtungen durchlaufen zu können (Hintergründe wieder zurückschreiben), also wäre eine doppelt verkettete Liste angebracht. Die benötigen nur etwas mehr Speicher, an der Geschwindigkeit ändert sich dadurch nichts. Zitat: Bei AmigaOS gibts für beinahe Alles Listen Zitat: Ja, wäre besser, generell für jedes Objekt ein Neuzeichnen vorzusehen. Es ist zwar etwas speicherintensiver aber dafür sparts Zeit. Sämtliche Überprüfungen bezüglich der Tiefenstaffelung fallen weg und ein paar andere Überprüfungen damit ebenfalls. Wenn Du diese eingesparte Zeit auf, sagen wir, 50 Frames hochrechnest kommt da einiges zusammen. Zitat: Wie gesagt, wenn Du noch weitere Frage hast, kannst Dich gern melden, ich versuch dann, Dir so gut wie irgend möglich weiter zu helfen. Animierte 2D-Grafik ist selten geworden auf dem Amiga, das muß man wieder ein wenig ausbauen Grüße [ - Answer - Quote - Direct link - ] |
2004-07-25, 00:34 h Reth Posts: 1858 User |
@whose Meine Mail schon angekommen (frag nur, weil evtl. ist sie in Deinem SPAMFilter hängen geblieben?)? [ - Answer - Quote - Direct link - ] |
2004-07-25, 04:17 h whose Posts: 2156 User |
Du hast Post Grüße [ - Answer - Quote - Direct link - ] |
2004-07-30, 15:43 h bubblebobble Posts: 707 User |
Du rettest die Hintergründe der Objekte ? Das ist nicht gut. Grafikkarten können sehr schnell Daten auf die Graka transportieren, aber nur sehr langsam lesen. Deshalb: Schreibe eine Funktion, die einen beliebigen Bildschirm Ausschnitt refresht, und zwar komplett, also Hintergundbild malen plus alle Objekte der Reihe nach. (Dazu Layers & Regions verwenden!). So musst du nie was retten, nur immer neu Zeichnen. Das ist besonders auf Grafikkarten und vielen Objekten wesentlich effizienter als Hintergrund retten. Du machst das am besten so, dass du nach jedem Frame eine "Damage" Liste erstellst, mit den rechteckigen Bereichen die zu aktualisieren sind. Wenn sich ein Objekt bewegt ist das also die komplette alte Rechteck und die das neue Rechteck drumherum. Wenn die Rechtecke sich überlappen kannst du noch eine Optimierung einbauen, dass die Bereiche zusammengefasst werden. Wenn sich ein Objekt nur in sich verändert, also nicht vortbewegt, genügt ein Refresh-Rechteck. Nachdem alle Bewegungen durchgeführt wurden und alle "zerstörten" Bereiche in der Damage List sind, kann diese abgearbeitet werden. So funktioniert ürigends AsteroidsTR, und damit sind bei 50fps schon eine ganze Reihe Objekte möglich, auch auf einem Classic und einer CyberVision 64 3D. Wenn sich die Objekte fast in jedem Frame bewegen, ist es vielleicht sogar noch besser immer komplett alles neu zu zeichnen. Klingt am Anfang verschwenderisch, ist aber auf jeden Fall schneller und logistisch wesentlich einfacher als Hintergründe zu retten, das ist ein Relikt aus OCS/AGA zeiten, wo lesen und schrieben in den Graka RAM gleich schnell waren. -- Thilo Köhler, Author von: HD-Rec, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, UDM, TKPlayer, TKUnpacker Homepage: http://www.hd-rec.de [ - Answer - Quote - Direct link - ] |
2004-07-31, 20:09 h Reth Posts: 1858 User |
Hallo bubblebobble,Zitat: Nehme dazu immer Blit-Funktionen des OS. Zitat: Hm dann sollte ich am besten wohl immer alles neu zeichnen. Kannst Du mir ein Beispiel für Layers und Regions schicken? Zitat: Klingt gut. Wenn ichs anders nicht in den Griff bekomme, werd ich das wohl mal probieren. Danke für die Tips! Ciao [ Dieser Beitrag wurde von Reth am 31.07.2004 editiert. ] [ - Answer - Quote - Direct link - ] |
2004-09-02, 11:47 h Reth Posts: 1858 User |
Weiss nicht, ob ich einen neuen Thread erstellen soll, aber: Habs nun mal soweit, dass ich in der Liste aller darstellbaren Objekte einmal pro Zeiteinheit durchlaufe. Dabei wird jedes Objekt gefragt, ob es aktualisiert werden muss. Wenn ja, wird dessen Hintergrund wiederhergestellt, und das Objekt selbst aktualisiert dargestellt. Im Anschluss daran werden alle Objekte, die "darüber liegen" können abgefragt, ob sie das eben aktualisierte Objekt überdecken. Ist das der Fall, wird deren Hintergrund erneut gesichert (da sich dieser ja verändert hat). Das hat den Vorteil, dass nur sehr kleine Bereiche geblittet werden müssen, dafür aber mehrere. Mit zunehmender Anzahl zu animierender Objekte wird das Ganze aber auch zunehmend langsamer. Wie kann man denn das Ganze optimieren? Einen ganz anderen Ansatz wählen (falls das Problem in diesem Thread schon "gelöst" wurde, einfach nochmal auf die Meldung hinweisen, denn dann hab ichs wohl nicht verstanden)? Danke vielmals Ciao [ - Answer - Quote - Direct link - ] |
2004-09-03, 11:13 h bubblebobble Posts: 707 User |
Wie gesagt, rette auf KEINEN Fall die Hintergründe! Bei modernen Grakas ist das so: Lesen von Graka ca. 2MB/sec schreiben auf Graka ca. 500MB/Sec, schreiben innerhalb der Graka 2000MB/sec oder mehr. Die Angaben sind qualitativ gemeint, schwanken natürlich von System zu System, aber du siehst die Unterschiede. Deshalb nochmal (beide Möglichkeiten sind doppelt gepuffert und flackern nicht!): =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1. Möglichkeit: Komplettrefresh =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Das ist schneller bei vielen Objekten, erfordert aber eine Mindestleistung der Grakas, sodass ein Classic schon etwas ins Schwitzen kommt, es geht aber noch mit 50fps. So funktioniert AsteroidsTR. Init: * Erstelle eine Bitmap für das Hintergrund Bild. * Erstelle eine Bitmap für die "Arbeitsbitmap". * Erstelle einen sichtbaren Screen in der Größe der Arbeitsbitmap. Bei Asteroids ist das so gelöst, dass der Screen einfach 3x so hoch ist wie sichtbar, dadurch ist garantiert dass alle drei Bitmaps im Graka RAM liegen, was sie aus Speedgründen auch dringend sollten. Eine Bitmap mit "friend screen" zu erstellen ist zu unsicher. Gameloop: Blitte die Hintergrundbitmap komplett auf die Arbeitsbitmap. Wenn es kein Hintergrund Bild gibt, dann musst du RecTFill() nehmen. Blitte alle Objekte neu auf die Arbeitsbitmap. Bitte die Arbeitsbitmap auf die Screenbitmap -voila. Zum Blitten immer BltBitmapRastPort() verwenden. Für Objekte mit Maske BltBitmapMaskRastPort() Diese Methode hat einen sehr hochen Grund-Aufwand, geht dafür nicht so schnell in die Knie wenn es viele Objekte gibt. Und normalerwiese ist es ja wichtig was bei vielen Objekten passiert, nicht ob der Overhead bei wenig Objekten gross ist, die laufen sowieso immer flüssig. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2. Möglichkeit: Damagelist =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Das ist wesentlich schneller bei wenigen Objekten, geht aber in die Knie bei vielen. Da aber die obige Methode bei wenigen Objekten auch schnell genug für GRakas ist, sollte man die eigentlich vor ziehen. Diese Methode kann man aber nutzen wenn keine Hardwarebeschleunigung vorhanden ist oder der Rechner sehr lahm ist. So funktioniert AsteróidsTR_CPU. Init: * Erstelle eine Bitmap für das Hintergrund Bild. * Erstelle eine Bitmap für die "Arbeitsbitmap". * Erstelle einen sichtbaren Screen in der Größe der Arbeitsbitmap. * Erstelle eine Liste mit "damage" Regionen, die wir uns merken wollen. Also eine Liste mit x1,y1,x2,y2 Koordinaten. Gameloop: Wenn sich ein Objekt bewegt, dann füge einen Eintrag in die DamageListe dazu mit den (x1 y1) (x2 y2) Koordinaten des umgebenden Rechtecks des Objekts. Es muss ein Eintrag gemacht werden für die alte Position UND für die neue Position des Objekts. Bei Überlappung (meistens so) kann man optimieren, indem man daraus einen einzigen Listenentrag macht mit jeweils den Extremen Punkten. Wenn sich nun alle Objekte "bewegt" haben, arbeiten wird die DamageList ab. For Each DamageListItem { Setze eine neue ClipRegion mit den Koordinaten des wiederherzustellenden Bereiches auf die Arbeitsbitmap. (InstallClipRegion()). Blitte Hintergrund und dann alle Objekte auf die Arbeitsbitmap. Evtl. kann man mit "if" abfragen, welche überhaupt in Frage kommen, ansonsten besorgt uns die ClipRegion das. Blitte den Bereich von der Arbeitsbitmap auf die Screenbitmap. Lösche die Region (InstallClipRegion() mit der alten Region). } fertig! So, das wars. Denke immer dran, für jedesmal wo du einen Rechteckigen Bereich AUS der Grafikkarte ausliesst, könntest du 20x das gleiche hineinblitten. -- Thilo Köhler, Author von: HD-Rec, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, UDM, TKPlayer, TKUnpacker Homepage: http://www.hd-rec.de [ - Answer - Quote - Direct link - ] |
2004-09-03, 13:24 h Reth Posts: 1858 User |
@bubblebobble Heißen Dank! Werde das Ganze mit den mehrfachen BitMaps mal probieren. Dachte mir halt, da ich nur sehr kleine Bereiche blitten muss (dafür aber manchmal umso mehr), machh ich das wie beschrieben, damit ich Speicher sparen kann. Bei der Mehrfach-Bitmaplösung brauch ich halt ne Menge RAM (Minimum 1024x768x8x2). Bin mir auch nicht sicher, inwieweit sich die INTUITICK bei mir als Bremser bemerkbar machen, da wenn das Ganze erstmal langsam ist und ich das Programm beende es manchmal mehrere Sekunden/Minuten dauert, bis das Programm zurückkehrt, obwohl Screen, Window, etc. schon alle geschlossen sind! [ - Answer - Quote - Direct link - ] |
2004-09-03, 19:27 h bubblebobble Posts: 707 User |
Zitat:Wenn sich viele Objekte überlappen, dann brauchst du auch viel Speicher, unter Umständen sogar mehr. Rechne mal nach. Auch kannst du davon ausgehen, dass ein Blitt immer serh schnell ist. Ein Blitvorgang hat aber eine Initialisierung, und die braucht recht lange. Wenn du also die gleiche Fläche blittest, und in 200 Teile zerteilst, dann ist das wesentlich langsamer. Zitat:Intuiticks sollte nichts damit zu tun haben. Das kostet dich so gut wie eine Rechenleistung. -- Thilo Köhler, Author von: HD-Rec, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, UDM, TKPlayer, TKUnpacker Homepage: http://www.hd-rec.de [ - Answer - Quote - Direct link - ] |
-1- | [ - Post reply - ] |
amiga-news.de Forum > Programmierung > Grafik Geschwindigkeit | [ - Search - New posts - Register - Login - ] |
Masthead |
Privacy policy |
Netiquette |
Advertising |
Contact
Copyright © 1998-2024 by amiga-news.de - all rights reserved. |