Als Lernübung habe ich eine verzögerte Rendering-Engine geschrieben. Jetzt möchte ich dieser Engine ein Szenendiagramm hinzufügen, aber ich bin ein bisschen verwirrt, wie das geht.
Bei einer normalen (Forward-Rendering-Engine) würde ich einfach alle Elemente (alle, die IDrawable und IUpdateAble implementieren) zu meinem Szenendiagramm hinzufügen, dann zuerst die Breite des Szenendiagramms durchlaufen und überall Draw () aufrufen.
In einer verzögerten Rendering-Engine muss ich jedoch Draw-Aufrufe trennen. Zuerst muss ich die Geometrie zeichnen, dann die Schattenwerfer und dann die Lichter (alle zu verschiedenen Renderzielen), bevor ich sie alle kombiniere. In diesem Fall kann ich also nicht einfach über das Szenendiagramm fahren und einfach Zeichnen aufrufen. So wie ich es sehe, muss ich entweder dreimal über das gesamte Szenendiagramm fahren und prüfen, welche Art von Objekt gezeichnet werden muss, oder ich muss drei separate Szenendiagramme erstellen, die irgendwie miteinander verbunden sind. Beides scheint eine schlechte Lösung zu sein. Ich möchte Szenenobjekte transparenter behandeln.
Eine andere Lösung, an die ich gedacht habe, war, wie gewohnt durch das Szenendiagramm zu reisen und Elemente zu 3 separaten Listen hinzuzufügen, Geometrie, Schattenwerfer und Lichter zu trennen und diese Listen dann zu wiederholen, um das richtige Material zu zeichnen. Ist das besser und ist es? klug, 3 Listen pro Frame neu zu füllen?
quelle
Mein Vorschlag wäre ein zweistufiger Ansatz, der auf Ihre spezifischen Anforderungen zugeschnitten ist, ähnlich wie Sie es selbst beschrieben haben. Sie benötigen für jeden Rendering-Schritt ein Szenendiagramm und eine "Render-Sammlung", in Ihrem Fall Schatten, Geometrie, Lichter (vielleicht ist ein vierter transparente Objekte?)
Das Szenendiagramm kann auf jeder Art von Beziehungen basieren, aber meine persönliche Präferenz würde auf räumlichen Beziehungen basieren, bei denen jeder Knoten die anderen Knoten enthalten kann, um ein schnelles Keulen zu ermöglichen.
Die Render-Sammlungen können beliebige Datenstrukturen sein, die auf den jeweiligen Schritt zugeschnitten sind. Beispielsweise könnte die Schattensammlung eine Liste oder ein Baum sein, die nach Tiefe sortiert sind, um die frühzeitige Z-Zurückweisung zu maximieren. Die Geometriesammlung kann nach Shader-Verwendung sortiert werden, um Shader- (Status-) Änderungen zu minimieren. Die Lichtsammlung kann eine Liste oder ein Baum sein, sortiert nach Lichtabstand, Größe oder einer Kombination davon, sodass Sie die Lichtwiedergabe nur auf die effektivsten Lichter beschränken können, wenn die Leistung ein Problem darstellt.
Unabhängig davon, welche Datenstrukturen Sie auswählen, stellen Sie sicher, dass der Einfügevorgang schnell ist, und stellen Sie sicher, dass Pooling und andere Techniken verwendet werden, um jegliche Zuordnung / Zerstörung von Daten zu vermeiden, da Sie diese Listen in jedem Frame löschen und füllen.
Jetzt ist es einfach, alles zusammenzubinden. Gehen Sie einfach durch das Szenendiagramm und fügen Sie jedes Element der entsprechenden Render-Sammlung (en) hinzu. Es ist hilfreich, wenn Ihre Datenstruktur neue Einträge automatisch nach den Anforderungen sortiert / strukturiert. Wenn Sie fertig sind, gehen Sie die Render-Sammlungen in der gewünschten Reihenfolge durch und rendern Sie sie.
Da Ihre Datenstrukturen schnell eingefügt werden und keinen Müll erzeugen, gibt es keine Strafe für das erneute Auffüllen von Listen, wie Sie erwähnt haben.
quelle