Was sind die gängigen Rendering-Optimierungstechniken für den Geometriedurchlauf in einem verzögerten Shading-Renderer? [geschlossen]

16

Ich habe eine Spiel-Engine mit OpenGL 3 und C ++ (und glfw für die Fensterverwaltung) entwickelt. Ich bin so weit fortgeschritten, habe die meisten Dinge erledigt, mit Ausnahme von Klangelementen und Optimierungen. Die Engine verwendet verzögertes Shading. Da verzögertes Shading für eine durchschnittliche GPU selbst ein anstrengender Prozess ist, möchte ich den Rendering-Prozess so weit wie möglich optimieren.

Das aktuelle System besteht aus einer Szene, die einen Renderer und die aktuelle Welt enthält, und die Welt enthält Objekte und Beleuchtungsobjekte als separate Objekte std::vectors.

Grundsätzlich jedes Mal, wenn die Scene aufgerufen wird ->render()und den Renderer aufruft, wird die Welt als Parameter übergeben, und es werden die Entity-Iteratoren aus der Welt abgerufen, sie werden in den FBO gezogen und dann werden die Lighting-Entities für den zweiten Durchgang durchlaufen. Und ich denke das ist nicht genug.

Mein aktueller Algorithmus durchläuft alles, auch wenn sich die Entität nicht im Bildschirmbereich befindet. Ich denke über eine Möglichkeit nach, den aktuellen Rendering-Algorithmus so zu optimieren, dass nur die API-Funktionen für die sichtbaren Objekte aufgerufen werden. Was sind also die gebräuchlichen Techniken zur Optimierung eines solchen Renderers?

deniz
quelle

Antworten:

40

Die verzögerte Schattierung ist nur eine Technik, um die eigentliche Schattierungsoperation für spätere Stadien "aufzuschieben". Dies kann großartig sein, um die Anzahl der Durchgänge zu verringern, die (zum Beispiel) benötigt werden, um 10 Lichter zu rendern, die 10 Durchgänge benötigen. Mein Punkt ist, dass es unabhängig von der verwendeten Rendering-Technik bestimmte mögliche Rendering-Optimierungen gibt, die die Anzahl der Objekte (Scheitelpunkte, Normalen usw.) reduzieren, die Ihre Rendering-Pipeline verarbeiten muss.

Es gibt keinen De-facto-Standard für Rendering-Optimierungen, sondern eine Reihe von Techniken, die austauschbar oder zusammen verwendet werden können, um bestimmte Leistungsmerkmale zu erzielen. Die Verwendung jeder Technik hängt stark von der Art der gerenderten Szene ab.

Beim verzögerten Rendern wird versucht, das Problem zu lösen, wenn die Anzahl der Lichter zunimmt, wodurch beim vorwärts gerenderten Rendern die Anzahl der Durchgänge explodieren kann.

Diese Techniken optimieren den verzögerten Schattierungsteil nicht direkt, aber gemäß Ihrer Beschreibung ist der verzögerte Schattierungsteil NICHT Ihr Problem. Ihr Problem ist jedoch, dass Sie die gesamte Szene an die Rendering-Pipeline senden. Ihre Engine muss also alle 100 Millionen Vertices in Ihrer Szene verarbeiten (zum Beispiel alle 100 Millionen Vertices), um das Ergebnis an den G-Buffer übergeben zu können, während die meisten dieser 100 Millionen Vertices trivial entfernt und nicht an den übergeben werden können Scheitelpunkt und Fragmente werden vorverarbeitet.

Im Falle eines Forward-Renderers wird der N-Vertex von der Vertex-Stufe insgesamt vertex count*lights countund von der Fragment-Stufe insgesamt verarbeitet fragments count*number Lights. Eine verzögerte Schattierung reduziert dies effektiv auf nur vertex countfür die Vertex-Stufe und fragments countfür die Fragment-Zählung, bevor das aufgelöst wird tatsächliche Schattierung. Dennoch kann N zu viel sein, um verarbeitet zu werden, insbesondere wenn die meisten von ihnen trivial gekeult werden können.

Dies macht das Culling bei Forward-Rendering / mehreren Durchläufen effektiver. Bedenken Sie jedoch, dass die meisten Engines einen Dual-Rendering-Ansatz verwenden, da verzögertes Shading allein keine transparenten Objekte auflösen kann. Daher ist die Verwendung dieser Optimierungen ein Muss. Ich kenne keine kommerzielle Engine, die nicht alle von ihnen ausführt.

Frustum Culling

Es müssen immer nur Objekte an die Rendering-Pipeline übergeben werden, die ganz oder teilweise im Ansichtsstumpf enthalten sind. Dies ist das Grundkonzept der Kegelstumpfentfernung. Leider kann es eine teure Operation sein, zu prüfen, ob sich ein Netz in der Ansicht befindet oder nicht. Stattdessen verwenden Konstrukteure ein ungefähres Begrenzungsvolumen, wie z Auch wenn dies möglicherweise nicht so genau ist wie die Verwendung des tatsächlichen Netzes, lohnt es sich nicht, den Genauigkeitsunterschied mit dem tatsächlichen Netz zu überprüfen.

Bildbeschreibung hier eingeben

Selbst bei Bounding-Volumes müssen Sie nicht jedes einzeln überprüfen. Alternativ können Sie eine Bounding-Volume-Hierarchie erstellen, um ein früheres Culling durchzuführen. Dies hängt in hohem Maße von der Komplexität der Szene ab.

Dies ist eine gute und einfache Technik für einen kleineren Motor und wird fast in jedem Motor verwendet, den ich jemals verwendet habe. Ich empfehle die Verwendung einer "normalen" Bounding Volume / Frustum-Prüfung ohne Hierarchien, wenn Ihre Engine nicht das Rendern sehr komplexer Szenen erfordert.

Bounding Volume Hierarchy

Keulen des hinteren Gesichts

Dies ist ein Muss, warum Gesichter zeichnen, die sowieso nicht sichtbar sind? Rendering-APIs bieten eine Schnittstelle zum Ein- und Ausschalten des Culling von Rückseiten. Dies ist ein Muss, es sei denn, Sie haben einen wichtigen Grund, warum Sie es nicht einschalten sollten, wie einige CAD-Anwendungen, die unter bestimmten Umständen Backfaces zeichnen müssen.

Occlusion Culling

Mit dem Z-Buffer können Sie die Sichtbarkeitsbestimmung auflösen. Das Problem ist jedoch, dass der Z-Buffer nicht immer sehr leistungsfähig ist, da der Z-Buffer erst in späteren Phasen der Pipeline aufgelöst werden kann. Zu verschließende Objekte sollten gerastert und möglicherweise in den Z-Buffer und in den geschrieben werden Farbpuffer vor dem Nichtbestehen des Z-Tests.

Occlusion Culling behebt dieses Problem, indem einige frühe Tests durchgeführt werden, um verschlossene Objekte zu entfernen, die sich im Rendering-Kegelstumpf befinden. Eine praktische Implementierung von Okklusions-Culling besteht darin, punktbasierte Abfragen zu verwenden und zu überprüfen, ob bestimmte Objekte aus einer bestimmten Perspektive sichtbar sind. Dies kann auch zum Löschen von Lichtquellen verwendet werden, die nicht zum endgültigen Bild beitragen. Dies ist insbesondere in einem verzögerten Engine-Renderer hilfreich.

Bildbeschreibung hier eingeben

Ein großartiges Beispiel für eine solche Technik in der realen Welt ist GTA5, wo die Wolkenkratzer strategisch in der Mitte der Stadt platziert sind, nicht nur Dekorationen sind, sondern auch als Okkluder fungieren, um den Rest der Stadt effektiv zu verschließen und zu verhindern, dass er ist gerastert.

LOD

Detaillierungsgrad

Der Detaillierungsgrad ist eine weit verbreitete Technik. Die Idee ist, eine einfachere Version des Netzes zu verwenden, wenn das Netz weniger zur Szene beiträgt. Es gibt zwei gängige Implementierungen. Man tauscht einfach das Netz gegen ein einfacheres aus, wenn es keinen großen Beitrag mehr leistet. Das Netz wird basierend auf einem Faktor wie dem Abstand und der Anzahl der Pixel (Fläche auf dem Geröll) ausgewählt, die das Netz einnimmt. Bei der anderen Version wird das Netz dynamisch tesselliert, was beim Rendern im Gelände weit verbreitet ist.

Bildbeschreibung hier eingeben

Was ist, wenn all dies nicht funktioniert?

Das ist eine gute Frage.

Als Erstes müssen Sie Ihre Anwendung mit einem Grafikprofiler profilieren und den Engpass ermitteln. Beachten Sie, dass sich der Engpass ändern kann, wenn sich der gerenderte Inhalt ändert. Möglicherweise sind auch Engpässe Teil des auf der CPU ausgeführten Codes, sodass Sie dies ebenfalls messen müssen.

Nachdem Sie einige Optimierungen am Engpass vorgenommen haben, müssen Sie berücksichtigen, dass es keine richtige Antwort dafür gibt und sich von Hardware zu Hardware unterscheiden wird.

Einige gebräuchliche Tricks zur GPU-Optimierung:

  • Verzweigung in Shadern vermeiden.
  • Probieren Sie verschiedene Scheitelpunktstrukturen aus, die beispielsweise {VNT}in demselben Array oder {V},{N},{T}in verschiedenen Arrays verschachtelt sind .
  • Szene von vorne nach hinten zeichnen.
  • Schalten Sie den Z-Buffer an einigen Stellen aus, zum Beispiel wenn ein Bild keinen Z-Test benötigt.
  • Verwenden Sie komprimierte Texturen.

Einige allgemeine Tricks zur CPU-Optimierung:

  • Verwenden Sie Inline-Funktionen für kleine Funktionen.
  • Verwenden Sie nach Möglichkeit SIMD (Single Instruction Multiple Data).
  • Vermeiden Sie Cache-unfreundliche Speichersprünge.
  • Verwenden Sie VBOs mit der "richtigen" Datenmenge. (je nach Hardware) Meistens sind aber weniger Draw Calls besser.

Aber was ist, wenn mein Engpass in der verzögerten Schattierung lag?

In diesem Fall besteht der offensichtlichste Teil darin, die tatsächlichen Schattenberechnungen zu optimieren, da sich die verzögerte Schattierung mehr um das Licht kümmert. Einige Punkte, die Sie im Auge behalten sollten:

  • Rendern Sie Lichter, die sich tatsächlich auf das endgültige Bild auswirken. Mit anderen Worten: Schalten Sie die Lichter aus, die nicht dazu beitragen. Dies kann unter Verwendung des zuvor erwähnten Okklusions-Cullings effektiv implementiert werden.
  • Benötigt diese Leuchte das Spiegelglas oder andere Komponenten? Vielleicht nicht.
  • Wirft dieses Licht Schatten? Einige Lichter müssen keine Schatten werfen.
  • Kann dieser Lichtbeitrag vorberechnet werden? Wenn es sich nicht bewegt, können wahrscheinlich einige Aspekte vorberechnet werden.
concept3d
quelle
Entschuldigung, diese haben nichts mit verzögerter Schattierung zu tun. Es handelt sich tatsächlich um die exakten Leistungsprobleme, die durch die Technik effektiv gemildert werden, und daher um die am wenigsten nützlichen Optimierungen. Der Fokus sollte auf den Beleuchtungsdurchläufen liegen, denn wenn die Beleuchtungskosten nicht sind Der dominierende Zeitnehmer, die verzögerte Schattierung, ist wahrscheinlich die falsche Wahl.
MickLH
@ MickLH Leider haben Sie die Frage anscheinend nicht gelesen. Sein Problem bestand hauptsächlich darin, dass er jedes Mal über die gesamte Szene iteriert und keinen Engpass in Bezug auf die zurückgestellte Schattierung erwähnt. Ich erwähnte zuerst, dass eine verzögerte Abschattung das Problem der Durchgangsexplosion löst, wenn viele Lichter / Materialien vorhanden sind. Aber ich fügte dann hinzu, dass diese Optimierungen für jede Engine ein Muss sind, unabhängig davon, ob die Shading-Technik vorwärts oder rückwärts gerichtet ist. In Anbetracht der Tatsache, dass dies genau die Themen sind, denen die Technik widerspricht, kann ich hier nicht alle Punkte
ansprechen
Es ist wirklich dumm, eine verzögerte Engine zu bauen, ohne zum Beispiel Kegelstumpf auszusortieren, also wird die Engine zum Beispiel (100 Millionen Vertex) verarbeiten, nur um in der Lage zu sein, das Ergebnis an den G-Buffer zu senden. Die unterschiedliche Schattierung löst ein anderes Problem, das nicht sein Problem war. Sein Problem bestand darin, die gesamte Geometrie an die Pipeline zu übergeben.
concept3d
Ich stimme zwar darin überein, dass einige Optimierungen bei den Beleuchtungsberechnungen vorgenommen werden sollten, und wenn Lichtberechnungen nicht die vorherrschende Rolle spielten, dann ist eine Verschiebung der falsche Weg. aber auch das war nicht sein problem.
concept3d
Ich werde meine Ablehnung zurückziehen, wenn Sie klarstellen, dass diese Optimierungen für einen verzögerten Renderer tatsächlich am wenigsten effektiv sind, da Sie ihm / ihren + Googlern anscheinend nicht gezeigt haben, dass das Leistungsproblem nichts mit verzögerter Schattierung zu tun hat.
MickLH
6

Ihr Problem hängt überhaupt nicht mit verzögerter Schattierung zusammen . Sie müssen die grundlegenden Kernelemente eines Renderers implementieren, bevor Sie versuchen, einen bestimmten Teil zu beschleunigen.

Wenn Sie mit den Erläuterungen von concept3d fertig sind und tatsächlich feststellen, dass Sie den verzögerten Shader selbst (im Gegensatz zum gesamten Rasterungsdurchlauf) optimieren müssen, können Sie Tile-Based Deferred Shading implementieren.

Wenn Sie sich nicht durch die Anzahl der dynamischen Lichter begrenzt sind , sollten Sie darüber nachdenken , warum Sie Deferred Shading überhaupt verwenden, aber wenn Sie sind dann sollten Sie die Optimierung , um zu versuchen , dass Battlefield 3 möglich gemacht haben . (Sie verweisen darauf in Folie 10 ihres öffentlichen PDF: http://dice.se/wp-content/uploads/GDC11_DX11inBF3_Public.pdf )

MickLH
quelle