Ich überarbeite einige Teile der Spiel-Engine, an der ich arbeite. Diese Engine wird in C # mit XNA hergestellt.
Der Teil, mit dem ich Probleme habe, ist Shader / Material und die Render-Warteschlange. In der neuen Version werde ich die Möglichkeit geben, unterschiedliche Renderzustände pro Durchgang innerhalb einer Technik anzugeben (Mischzustand, Rasterzustandszustand, ...). In meiner Engine haben alle Renderables ein Material und jedes Material ist einer Technik zugeordnet (also einem oder mehreren Durchgängen).
Später, wenn das Spiel ausgeführt wird, füge ich der Renderwarteschlange renderbare Objekte hinzu und sortiere sie dann nach dem von jedem Material verwendeten Durchgang. Was ich erreichen möchte, ist, Zustandsänderungen zwischen Draw Calls zu reduzieren, indem zuerst dieselben Durchgänge zusammengefasst und dann mit nahezu identischen Zuständen so geschlossen wie möglich geschlossen werden, um Änderungen zu minimieren. Diese Lösung scheint jedoch problematisch zu sein, wenn es darum geht, Techniken mit mehr als einem Durchgang mit völlig unterschiedlichen Zuständen zu verwenden. Durchläufe innerhalb derselben Technik können in der Renderwarteschlange vollständig getrennt und nicht nacheinander gerendert werden. Wenn ich sage, dass es daran liegt, dass ich immer gesehen habe, wie die Technik mit mehreren Durchgängen in einer Schleife gerendert wird und alle Durchgänge sofort so gerendert werden:
foreach(EffectPass pass in technique.Passes)
{
/* Update parameters */
pass.apply();
graphicsDevice.Draw(...);
}
Ich weiß jedoch nicht, ob ich das Pass-Rendering mit derselben Technik verschieben kann, anstatt sie wie im vorherigen Beispiel nacheinander zu verwenden.
Hier ist ein Beispiel dafür, was wahrscheinlich mit der Lösung passieren wird, die ich zu erstellen versuche:
- Shader1
- TechnikA
- Pass1 (Zustand A)
- Pass2 (Zustand C)
- TechnikA
- Shader2
- TechnikB
- Pass1 (Zustand A)
- TechnikB
- Shader3
- TechnikC
- Pass1 (Zustand A)
- TechnikC
Jetzt muss ich drei Modelle zeichnen, Modell1, Modell2 und Modell3, die jeweils eine andere Technik als die vorherige Liste verwenden. Wenn ich diese drei Modelle in die Renderwarteschlange einfüge, wird die folgende Renderwarteschlange angezeigt:
-> Status A einstellen -> Modell1 zeichnen (Pass1) -> Modell2 zeichnen (Pass1) -> Modell3 zeichnen (Pass1) -> Status C setzen -> Modell1 zeichnen (Pass2)
Wir können sehen, dass das Modell1 zweimal gezeichnet wird (zwei Durchgänge für Technik A), aber der Zeichnungsaufruf wird durch einen anderen Zeichnungsaufruf getrennt.
Ich weiß nicht, wie ich das lösen soll. Was ist eine gute Lösung für dieses Problem? Wie kann ich meine Renderwarteschlange so gestalten, dass Statusänderungen zwischen Zeichnungsaufrufen so weit wie möglich reduziert werden?
BEARBEITEN:
Nachdem ich ein bisschen mehr gesucht habe, habe ich diesen hilfreichen Artikel gefunden: http://realtimecollisiondetection.net/blog/?p=86 . Es scheint eine elegante Art zu sein, Objekte nach Tiefe und Materialien zu sortieren. Und in der Material-ID kann ich eine Pass-ID haben, um denselben Pass zusammen zu sortieren, um Statusänderungen zu reduzieren.
Derzeit zeichnet mein Renderer Objekte direkt im Backbuffer ohne Licht oder Schatten, alles ist flach. Also werde ich einfach meine Renderwarteschlange durchlaufen und Zeichenmethoden aufrufen. Aber in Zukunft werde ich wahrscheinlich das verzögerte Rendern implementieren.
Ich weiß nicht viel darüber, aber ich weiß, dass ich meine Objekte in verschiedenen Renderzielen rendern muss, um verschiedene Informationen zu sammeln (Z-Puffer, Normaler Puffer, G-Puffer, ...). Ich gehe davon aus, dass ich für Z-Puffer und normalen Puffer für alle Objekte den gleichen Shader verwenden werde, unabhängig davon, welches Material sie verwenden. Aber für den G-Puffer werde ich die Materialien jedes Objekts verwenden, was unterschiedliche Shader mit unterschiedlicher Anzahl von Durchgängen bedeutet. Wenn ich die Lösung im vorherigen Link verwende und ein Objekt mit einem Material habe, das zwei oder mehr Durchgänge ausführen muss, hat meine Renderwarteschlange mindestens das Zweifache des Objekts (einen für jeden Durchgang). Aber für Z-Puffer oder normalen Puffer ist es nicht nutzlos, dasselbe Objekt mehrmals zu haben?
Was ich sehe, ist, dass ich mindestens zwei verschiedene Renderwarteschlangen haben muss: eine für den G-Puffer, in der sich ein Objekt je nach Anzahl der Durchgänge, die das Material benötigt, mehrmals befinden kann, und eine andere Renderwarteschlange für den Z-Puffer oder einen anderen Puffer in denen jedes Objekt nur einmal ist. Habe ich recht?