Registriert: Di Apr 29, 2008 18:56 Beiträge: 1213
Programmiersprache: Delphi/FPC
Hey,
ich arbeite zur Zeit an einer Visualisierung für Musik. Funktioniert auch alles, doch es läuft bei 75FPS mit 100% CPU Last. Und ich weiß nicht wirklich wie ich das verbessern kann. Ich habs schon mit VBOs bersucht, aber da muss ich immer die Zeiger umkopieren un das frist mehr Leistung als vorher. Hat jmd von euch ne Idee, wie ich das schneller hin bekomm?
Registriert: Sa Aug 18, 2007 18:47 Beiträge: 694 Wohnort: Köln
Programmiersprache: Java
Moin,
ich schätze mal, dass die Last auf 100% bliebe wenn du nur ein Quad rendern würdest. Und die 75 FPS rühren wohl vom VSync her? Versuch mal den VSync zu deaktivieren.
Zitat:
Ich habs schon mit VBOs bersucht, aber da muss ich immer die Zeiger umkopieren un das frist mehr Leistung als vorher. Hat jmd von euch ne Idee, wie ich das schneller hin bekomm?
Was meinst du mit "umkopieren"? Du brauchst doch nur den Pointer um die Recordgröße inkrementieren.
_________________ Es werde Licht. glEnable(GL_LIGHTING); Und es ward Licht.
Zitat aus einem Java Buch: "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off"
Meine Erfahrung mit mancher Software vor der Generation Hardware T&L ist, dass sie auf einer TNT2 besser läuft als auf einer Geforce 8600. Du solltest durchaus bei deinem Ansatz bleiben und auch einen modernen Renderpfad ohne Immediate Mode anbieten. glVertex, glColor und co. sind in OpenGL 3 nur noch Altlasten. Das ist der Konsens bei den Entscheidern und vermutlich den Grafikkartenherstellern. Neue Grafikkarten können sehr gut paralellisieren. Das geht aber nur wenn sie Daten in Blöcken bekommen und nicht garnicht gut im Immediate Mode.
Ich habe auch mal gelesen, dass es besser sei, sich den OpenGL State zu merken, als ihn redundant immer wieder auf das selbe zu setzen. Bringt wahrscheinlich in deinem Fall aber nicht viel da du ja nur den Blend-Mode setzt.
Wie genau hast du das mit den VBOs denn gemacht? glMapBuffer? Beim Anlegen darauf geachtet, OpenGL auf die häufigen Änderungen hinzuweisen? Siehe auch: http://www.songho.ca/opengl/gl_vbo.html#update
Der VBO sollte auch nicht jedes mal neu erstellt werden. Wie NerdIII schon andeutet sollte der Typ des VBO entweder GL_STATIC_DRAW oder GL_STREAM_DRAW sein. Für deinen Fall sollte STREAM luat Beschreibung eigentlich schneller sein, ich habe aber die Erfahrung gemacht das STATIC manchmal trotzdem schneller ist. Beim glMapBuffer solltest du GL_WRITE_ONLY angeben.
Wenn sich sowieso jedes Frame alles ändert kannst du alternativ auch einfach Vertexarrays benutzen. So kannst du direkt aus einem Array rendern. Das schreiben des VBO wird dann von OpenGL übernommen.
Registriert: Do Sep 25, 2003 15:56 Beiträge: 7810 Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Wo die 100% herkommen kann ich dir fast mit Sicherheit sagen: Du nutzt den onIdle handler, oder?
OnIdle sorgt dafür, dass dein Prozessor eben nicht mehr faul ist. Er beschäftigt ihn dauerhaft.
Wenn du die Leistungsaufnahme etwas runterregeln willst gibts zwei Möglichkeiten:
1. du baust ein sleep ein. Am besten kombiniert mit ApplicationProcessMessages (oder wie das heißt).
2. Du steigst auf einen Timer um und renderst mit fest vorgegebener Framezahl. Das wäre in deinem Fall vermutlich besser, da du keine FPS Monster Anwendung benötigst.
_________________ Blog: kevin-fleischer.de und fbaingermany.com
Registriert: Di Apr 29, 2008 18:56 Beiträge: 1213
Programmiersprache: Delphi/FPC
Hey,
ja ich hab alles im OnIdle, aber durch das vSync wird alles auf 75FPS begrenzt un das senkt auch die Rechenleistung. Wenn ich nur 1 Quad zeichne, dann hab ich fast 0% Last.
Das mit dem Umkopieren mein ich so: Die Visualisierung verschiebt die alten "Balken" nach hinten, wenn ein neuer vorn rein kommt, also muss ich jedesmal die die Daten im VBO umkopieren. Und das macht das ganze dann langsamer als vorher.
Ich habs mit STATIC und STREAM_DRAW versucht, aber kein unterschied. Ich denk ma bei 15FPS merkt man das auch nich wirklich...
Mit VertexArrays hab ichs noch nich versucht, aber da kann ich ja dann mit den Indices arbeiten, das sollte das alles ein bisschen schneller machen, ich guck ma obs was bringt.
Registriert: Di Okt 13, 2009 17:25 Beiträge: 365
Programmiersprache: C++
@Timer: Von dem Ding kann ich dir nur abraten, da es ziemlich ungenau ist. Wenn du dort ein Interval von 40 ms angibst (entspricht ja 25 FPS), heißt das, dass Betriebssystem *mindestens* 40 ms wartet, bis die Timer-Funktion aufgerufen wird. Meinen Erfahrungen nach, resultiert das dann darin, dass ein Interval von 40 ms zu 21 FPS und 30 ms zu 28 FPS und sowas führt.
Für meine Projekte habe ich mir deshalb eine Klasse geschrieben, die eine Warten-Funktion besitzt. Dabei wird die Zeit gemessen, die seit dem letzten Frame vergangen ist und die Hälfte der Zeit, die noch über ist, mit Sleep() gewartet. Da das immernoch nicht genau genug ist, wird ab 12 ms vor dem nächsten Frame 0 ms gewartet (also Sleep(0);) und ab 1 ms vor dem nächsten Frame einfach nur noch in einer Endlosschleife solange gemessen, bis die Zeit für den nächsten Frame gekommen ist.
MfG
mrtrain
Zuletzt geändert von mrtrain am Mi Aug 31, 2011 18:02, insgesamt 1-mal geändert.
Und das macht das ganze dann langsamer als vorher.
Das kann eigentlich nicht sein, du machst irgendwas falsch. Vielleicht das GL_WRITE_ONLY vergessen? Das ist nämlich wesentlich da sonst die Daten erst noch von der Grafikkarte in den RAM geholt werden müssen, also doppelt kopiert werden.
Zitat:
Die Visualisierung verschiebt die alten "Balken" nach hinten, wenn ein neuer vorn rein kommt, also muss ich jedesmal die die Daten im VBO umkopieren.
Ich habe mir nicht angeschaut was du da genau machst, aber wenn du du eigentlich immer nur ein Element neu einfügst musst du nicht immer den ganzen Buffer neu schreiben, sondern nur dieses eine Element. Da du hier von Balken redest nehme ich an, dass ein Balken immer ein Quad ist. Nur wenn sich einzelne Balken nicht überschneiden könnte es beim Blending Probleme geben, ansonsten ist der Grafikkarte die Reihenfolge völlig egal. Du kannst einfach gezielt immer das älteste Quad überschreiben. Das machst du natürlich mit glBufferSubData, damit wirklich nur die veränderten Daten übertragen werden.
Angenommen dein Buffer hat die Größe N und am Anfang ist das älteste Element vorne im Buffer (Position 0) und das neueste hinten (Position N-1). Beim ersten Update überschreibst du Position 0, beim zweiten Position 1, beim dritten Position 2 usw. bis N-1, dann fängst du wieder bei 0 an. Einfachste Lösung:
Registriert: Di Apr 29, 2008 18:56 Beiträge: 1213
Programmiersprache: Delphi/FPC
Hey,
GL_WRITE_ONLY hab ich drin. Ich hab ma n Bild angehängt, was verdeutlicht, was ich vor hab. Die Blauen Balken ganz vorn sind die aktuellen Daten, die dann nach hinten verschoben werden, wenn neue Daten da sind. Un da muss ich jetz alle Reihen eins weiter nach hinten verschieben. Die Zeichenreihenfolge ist auch wichtig, da ich Blending verwende. Deshalb wollt ich das über die Indices probieren, so das ich die letze Reihe mit der neuen überschreib, un dann bloß die Indices um eins verschiebe. Schreiben bzw. Lesen aus dem VBO hab ich bis jetz immer so gemacht: Ich hab mir die Startadresse im Speicher besorgt und dann einfach index*size draufgezählt um den aktuellen Vertex zu erhalten...
MfG Bergmann
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
Da ist das Problem: Du solltest auf das lesen verzichten
Zitat:
Die Blauen Balken ganz vorn sind die aktuellen Daten, die dann nach hinten verschoben werden, wenn neue Daten da sind. Un da muss ich jetz alle Reihen eins weiter nach hinten verschieben.
Achso, ich sehe das Problem. Du könntest allerdings eine Translations-Matrix benutzen, also glTranslate um die Daten zu verschieben. Das geht natürlich nicht endlos, weil die Zahlen zu groß werden. Hin und wieder musst du also doch komplett neu schreiben, aber nicht jedes Frame.
Ein anderer Ansatz wäre die Daten aufzuteilen. Ich nehme mal an die Farben bleiben gleich? Dann musst du die ja schon mal nicht neu schreiben. Also ein VBO für Vertex-Position, ein VBO für Farben.
Die Profi-Lösung wäre das im Vertexshader zu realisieren. Der Input ist ein VBO mit 3D-Vertices als Grundfläche. Dabei ist die dritte Koordinate immer nur 0.0 oder 1.0, je nachdem ob im Shader die Höhe aufaddiert werden soll oder nicht. Diese Grundfläche bleibt immer unverändert. Die echten Höhendaten und Farben werden aus einer RGBA-Textur (besser TBO) gelesen. Über ein Integer-Uniform steuerst du wo aus der Textur gelesen wird. Dieses Uniform wird in jedem Frame um eins weiter geschoben:
Code:
i := (i + 1) mod N;
Angenommen die X-Achse ist die wo geschoben werden soll dann berechnest du den Index für die Textur so:
Code:
vec2 texCoord =floor(vec2(gl_Vertex.x+ i,gl_Vertex.y));// das floor ist wichtig, da sich die 4 Vertices des Quads ja leicht unterscheiden, aber auf die gleiche Stelle der Textur zugegriffen werden soll
if(texCoord.x>= N){ texCoord.x-= N;}
texCoord /= N;// in den Bereich 0..1 bringen, Annahme: Textur quadratisch
Registriert: Di Apr 29, 2008 18:56 Beiträge: 1213
Programmiersprache: Delphi/FPC
Hey,
das mit den Shadern is ne gute Idee, aber da gibts 2 Sachen die mich stören: 1. ist das TBO erst mit Shader4.0 möglich, also fällt das für mcih schonma flach. Aber das kann ich ja bestimmt auch über ne normale Textur machen. 2. das Alpha kann ich nich für die Daten verwenden, da ich das ja für die Transparenz brauch. Also müsst ich noch ne 2. Textur mit den Daten binden, oder?! Aber jedesma die ganzen Daten in die Textur packen dauert ja auch wieder n ganzes Stück. Oder hab ich dich irgendwie falsch verstanden?!
nochma zu der Idee mit den 2 VBOs: wie kann ich denn überhaupt 2 VBOs auf einma binden? Ich hab bis jetzt immer nur mit einem gearbeitet. Weil ich denk ma damit gehts dann doch am bessten, da ich muss ich immer nur eine Reihe im VBO mit neuen Daten füllen und dann nur die Indices verschieben.
1. ist das TBO erst mit Shader4.0 möglich, also fällt das für mcih schonma flach.
Naja, du hast ja noch die Alternative, das über eine Textur zu machen. Du kannst ja die Verfügbarkeit von TBOs abfragen und anhand dessen entscheiden, was du benutzt.
1. ist das TBO erst mit Shader4.0 möglich, also fällt das für mcih schonma flach. Aber das kann ich ja bestimmt auch über ne normale Textur machen.
Korrekt, einfach Texturfilter auf GL_NEAREST stellen damit zu exakt auf die Texel zugreifen kannst. Beides zu implementieren würde ich nicht tun, so viel besser sind TBOs nun auch wieder nicht. Allerdings kannst du darüber nachdenken ob du texelFetch benutzen möchtest. Das erlaubt es mit Integer-Koordinaten auf die Textur zuzugreifen.
Zitat:
Aber jedesma die ganzen Daten in die Textur packen dauert ja auch wieder n ganzes Stück. Oder hab ich dich irgendwie falsch verstanden?!
Ja, aber die Datenmenge ist kleiner, weil du nur die Höhe und Farbe schreibst, nicht auch noch X und Y Koordinate. Ggf. kannst du dir die Farbe auch noch sparen, siehe nächster Punkt.
Zitat:
2. das Alpha kann ich nich für die Daten verwenden, da ich das ja für die Transparenz brauch.
Ja, in dem Fall bräuchtest du zwei Texturen. Allerdings....wie leiten sich den deine Farben und Alphawerte ab? Die Berechnung hängt doch wahrscheinlich letztlich nur vom i und ggf. der Höhe ab, nicht? Dann könntest du die Farbe/Alpha auch im Shader berechnen, dann brauchst du nur noch die Höhe.
Registriert: Di Apr 29, 2008 18:56 Beiträge: 1213
Programmiersprache: Delphi/FPC
Hey,
die Farben der 4 Eckpunkte kann der User selbst festelegen. Also kann ich die 4 Farben entweder als Uniform übergeben, oder wenn die Farben geändert werden ne neue Textur berechnen. Was wäre da schneller?
Achso....die Farbe ist nur für die vier Eckpunkte des ganzen Feldes definiert und es wird einfach über die Fläche interpoliert? Das schreit gerade zu nach Uniform....auf jeden Fall nicht mit in den Vertex packen.
Du kannst die Farbe dann anhand der Vertex-Position aus deinen vier Farb-Uniforms berechnen.
Mitglieder in diesem Forum: 0 Mitglieder und 28 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.