Wie der Titel schon sagt, frage ich mich nach einigen Programmen, die ich schon mit OpenGL geschrieben habe, wie ich es schaffen kann, dass diese schneller werden. Meine Programme waren nämlich nie besonders effizient, bei manchen konnte man auf langsamen Grafikkarten kaum mehr erkennen, was da eigentlich gerade über den Bildschirm fliegen sollte und so wieter... Blöderweise funktionieren nur alle nicht von mir geschriebenen Spiele auf meinem Computer super und laufen auch gut, jedenfalls um einiges schneller als meine Anwendungen
Gibt es Möglichkeiten (außer mit Culling, das ich immer benutze) OpenGL Programme effizienter zu machen?
Kann man pauschal nicht sagen, ohne die genauen Programme zu sehen und den Code, der da hinter steckt.
Was du aber machen kannst, ist mal mit einem Profiler darüber gehen. Das sind Programme, die messen die Zeit, wie lange jeder Funktionsaufruf dauert. Somit kannst du herausfinden, was bei dir die Performance frisst.
Eine spezielle Empfehlung für einen Delphi-Profiler kann ich dir gerade nicht geben, aber gibt es bestimmt. Einfach mal danach googlen.
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Ansonsten, einige Punkte, wo man schauen kann:
* Sinnvolle Zeichenreihenfolge: Häufige Textur/Material/Statewechsel vermeiden
* VertexBufferObjects oder DisplayListen (je nach Graka, ich empfehle aber ersteres) sind deutlich performanter als der Immediate Mode
* Shader (falls vorhanden) optimieren, eventuell eher verschiedene Versionen erzeugen als Ifs zu verwenden.
* Codeoptimierung des Compilers anschalten
* Assertions und andere Debugmittel (Stack- und Rangecheck und ähnliches) ausschalten
Die letzten beiden Punkte sind nur etwas für die "Release"-Versionen, also wenn du nicht gerade Debuggen willst.
Gruß Lord Horazont
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
1. Vermeide Kommunikation zwischen CPU und GPU. Lade nicht deine Texturen/Vertexdaten in jedem Frame neu auf die Grafikkarte hoch. Verwende Vertexbuffer-Objects. Wenn das nicht möglich ist weil sich die Daten ändern, überlege ob du da nicht einen Shader einsetzen kannst oder die Grafikkarte die Daten selbst ändern lassen kannst. Für letzeres Stichworte: Framebuffer-Objects und Transform-Feedback, ist aber beides als "Advanced" einzustufen.
2. Lieber etwas mehr rendern, wenn du dadurch glDraw***-Aufrufe einsparen kannst. Es spielt so gut wie keine Rolle ob du 500 oder 1 Polygon renderst, da ein glDraw***-Aufrufe alleine schon ziemlich viel Zeit braucht.
3. Nutze den Z-Buffer aus. Sortiere nicht deine Polygone einzeln nach der Entfernung zur Kamera (Painters-Algorithm), sondern verwende den Z-Buffer. Sofern du aufwendige Shader oder viele Texturen verwendest, rendere deine Objekte (nicht Polygone) von vorne nach hinten. (Also grob sortieren und den Rest den Z-Buffer machen lassen)
4. Wenn du viele identische Objekte renderst, überlege ob du Instancing einsetzen kannst. Gehört zu "Advanced" Themen und erfordert halbwegs aktuelle Grafikhardware.
5. Ein glDraw*** wird nicht sofort ausgeführt, d.h. die CPU erhält die Kontrolle zurück bevor die GPU fertig mit rendern ist. Erst beim SwapBuffers wird synchronisiert. Folglich gebe zuerst der Grafikkarte was zu arbeiten, rechne dann deine Spiellogik, Physik, etc. auf der CPU und rufe dann erst swapBuffers auf. Sowas geht natürlich nicht immer, aber man kann beispielsweise Physik und Rendern in zwei Frames aufspilten. Also du berechnest immer die Physik für das nächste Frame, während die GraKa das aktuelle Frame rendert.
6. NVIDIA GPU Programming Guide lesen: http://developer.nvidia.com/object/gpu_ ... guide.html
7. Beispielsweise bei einem (großen) Partikelsystem sollte man dafür sorgen, dass nahe beieinander liegende Partikel nicht direkt hintereinander im Vertexbuffer liegen. Ansonsten würden diese gleichzeitig gerendert (GPU arbeitet hoch parallel!!!) und die einzelnen Kerne der GPU müssten alle auf die selben Stellen im Framebuffer zugreifen. Das geht natürlich nicht, d.h. sie müssen aufeinander warten und sind somit insgesamt nur so schnell wie ein einzelner Kern!
=> entweder nach Z sortieren, oder zufällig anordnen.
(Solche Effekt merkt man wahrscheinlich aber erst am 500.000 Partikeln oder so die alle auf einem Haufen sind....)
Danke für die Tipps. Für mich als Anfänger klingen die noch etwas kompliziert, aber ich werde mich mal darum kümmern und vielleicht später noch mal hier rein gucken, wenn ich größere Programme schreibe.
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Zu 3.: Achte aber darauf, dass deine Transparenten und Blending-Abhängigen Polygone trotzdem von hinten nach vorne sortiert sind. Sonst funktionieren die nicht richtig.
Gruß Lord Horazont
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Registriert: Do Sep 25, 2003 15:56 Beiträge: 7804 Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Ich denke die Liste könnten wir in den Techniken&Algorithmen Teil des Wikis einfügen und dort Pflegen.
Ich bin durch CoolCats Liste auf die DrawXxxx aufmerksam geworden.
Die Spezifikation im Wiki ist zwar auf deutsch, aber irgendwie fehlen mir noch ein paar Codebeispiele und eine Erklärung was diese Zeichenmethode so bringt. Wie muss ein solches Array aussehen? Wie können die verschiendenen Daten (Vertex- und Texturkoordinaten, Farbe, Normale) übergeben werden? Halt sowas.
Mal eine konkrete Frage hinten ran:
Ich hab eine GUI geschrieben. Dort werden die einzelnen Componenten einzeln mit glBegin/End gezeichnet. Bei jedem Durchlauf immer wieder. Wäre es schneller, wenn ich anstatt die direkt zu zeichnen, alle in ein Array schreibe und am Ende, wenn alles fertig ist das Array rausschicke? Was passiert, wenn man zwischendurch die Textur ausschalten und einschalten will? Oder Blending? Muss man dann jeweils das bisherige Array abschicken, dann die Änderungen machen und wieder schicken, usw.? Ist das für diesen Anwendungsfall überhaupt sinnvoll?
_________________ Blog: kevin-fleischer.de und fbaingermany.com
Wäre es schneller, wenn ich anstatt die direkt zu zeichnen, alle in ein Array schreibe und am Ende, wenn alles fertig ist das Array rausschicke?
Müsste eigentlich. Wobei, ich würde OpenGL das übernehmen lassen: glBegin wenn du mit zeichnen anfängst und glEnd wenn die GUI komplett gerendert ist. Ansonsten ein Vertexbufferobject nehmen und mit GL_WRITE_ONLY direkt da rein schreiben. Also kein eigenes Array zum puffern dazwischen.
Zitat:
Was passiert, wenn man zwischendurch die Textur ausschalten und einschalten will? Oder Blending?
Shader einsetzen und das über die Vertexfarbe (etc.) steuern welche Textur du nimmst? Beim Blending setzt du dann im Fragmentshader Alpha auf 1.0.
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Vorallem kommst du bei ner GUI optimaler weg, wenn du ein VBO hast und da nur dann Änderungen machst (mit dieser Funktion, die einzelne Teile ändern kann, ohne das komplette VBO in den Speicher schieben zu müssen), wenn sich auch wirklich etwas ändert und ansonsten einfach nur die Zeichenmethode aufrufst.
Gruß Lord Horazont
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Ich hab ne Componente die nach einer gewissen Ruhezeit eine Animation abspielt. Sowas passt doch da irgendwie nicht rein, oder?
Nun, mir fallen jetzt zwei Arten ein das zu realisieren:
1. Du definierst einen Bereich wo deine Animation gerendert wird. Das hat dann nichts mit GUI zu tun, du benutzt einfach den Scissor-Test bzw. eigene Clip-Planes.
2. Du renderst zuerst in eine Textur und die Textur dann anschließend in ein Quad. Es ist einfach nur eine Textur, also kein Problem bei der obigen Technik.
Registriert: Di Mai 18, 2004 16:45 Beiträge: 2621 Wohnort: Berlin
Programmiersprache: Go, C/C++
Für Performance tracking kann ich bei VS CodeAnalyst empfehlen.
Generell Performance zu verbessern ist schwer, dass sind in der Regel Holzhammermethoden ala sprache wechseln, compiler flags anpasssen.
Viel Performance geht bei Schleifen und im Aufruf von Methoden weg.
Zu starke Klassen zerlegung führt zu langsammeren Code, da man mehr Methodenaufrufe hat und jeder aufruf kostet push,pop, call und dann noch abhängig von deinem Parameter design sogar teure copy funktionen.
Alles was in Schleifen läuft ist hochgradig Anfällig für Performanceverlust.
In Verbindung mit OpenGL werden oft veraltete technologien verwendet, die einfach in den heutigen Treibern nicht so gut optimiert oder gar vom design langsamer sind.
Genauere Infos kann man immer nur gebeben, wenn man ein bischen mit der Anwendung vertraut ist, die optimiert werden soll.
_________________ "Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren" Benjamin Franklin
Mitglieder in diesem Forum: 0 Mitglieder und 24 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.