Ich entwickle derzeit eine Spiel-Engine, die signierte Distanzfelder als Rendering-Technik verwendet, um eine reibungslose prozedurale Geometrie anzuzeigen (generiert mit einfachen Grundelementen wie den in Ihrem Link, um in Zukunft Julia- und IFS-Fraktale zu implementieren). Da meine Engine auf die prozedurale Generierung ausgerichtet ist und Zahlen so definieren muss , dass sie ray-marcher-freundlich sind, bin ich an einem guten Ort, um diese Frage zu beantworten: P.
In Bezug auf Streaming besteht die einfache Lösung darin, einen typisierten Puffer zu verwenden und ihn auf die GPU zu werfen, wenn Sie Ihren Ray-Marsch durchführen möchten. Jedes Element des Puffers ist ein komplexer Typ (z. B. eine Struktur in C / C ++), und jeder Typ enthält Elemente, die definieren, welche Funktion Sie zur Darstellung verwenden sollen, Position, Drehung, Skalierung usw. und eine durchschnittliche Farbe. Der Prozess vereinfacht sich dann auf:
- Wählen Sie Ihre Szene in eine überschaubare Teilmenge aus (beachten Sie, dass das Keulen von Kegelstumpf und das Keulen von Okklusionen teilweise sowieso automatisch vom Ray-Marching-Algorithmus ausgeführt werden).
- Übergeben Sie die Teilmenge in Ihren Render-Eingabepuffer
- Übergeben Sie den Puffer an die GPU, falls er noch nicht vorhanden ist, und rendern Sie Ihre Szene mit herkömmlichem Ray-Marching. Sie müssen eine Art pro-Schritt-Suche durchführen, um zu bewerten, welches Element im Eingabepuffer für jede Iteration des Ray-Marchers jedem Strahl am nächsten ist, und Sie müssen Transformationen auf beide Strahlen anwenden (in diesem Fall) Sie müssen die Figurendrehungen invertieren, bevor sie die GPU erreichen) oder die Distanzfunktionen selbst (Verschieben des Funktionsursprungs für Positionsänderungen, Anpassen von z. B. kubischen Seitenlängen für Skalenänderungen usw.). Der einfachste Ansatz besteht darin, die Strahlen vorher zu ändern Sie geben sie an die eigentliche Kerndistanzfunktion weiter.
Denken Sie in Bezug auf Figurenfarben daran, dass Sie mit Shadern sowohl komplexe Typen als auch Grundelemente definieren können;). Auf diese Weise können Sie alles in eine Struktur im C-Stil werfen und diese Strukturen dann von Ihrer Distanzfunktion zurückgeben.
In meiner Engine enthält jede Struktur einen Abstand, eine Farbe und eine ID, die sie mit der entsprechenden Figurendefinition im Eingabepuffer verknüpft. Jede ID wird aus dem umgebenden Kontext der relevanten Distanzfunktion abgeleitet (da meine Zuordnungsfunktion den Eingangspuffer durchläuft, um für jeden Schritt die nächstgelegene Zahl zu jedem Strahl zu finden, kann ich den Wert des Schleifenzählers sicher behandeln, wenn jede SDF aufgerufen wird als die Figuren-ID für diese Funktion), während Abstandswerte unter Verwendung einer beliebigen Kern-SDF definiert werden (zpoint - figure.pos
für eine Kugel), und Farben werden entweder aus der Durchschnittsfarbe des entsprechenden Elements im Figurenpuffer definiert (daher ist es nützlich, die Figuren-IDs beizubehalten) oder durch eine prozedurale Farbe, die in Richtung des gespeicherten Durchschnitts gewichtet ist (ein Beispiel könnte sein eine Iterationszahl für einen bestimmten Punkt auf der Mandelbulb, wobei Ihre "durchschnittliche Farbe" vom FP-Farbraum auf den ganzzahligen Farbraum abgebildet wird und dann die zugeordnete Farbe als Palette verwendet wird, indem sie mit der Iterationszahl XOR-verknüpft wird).
Prozedurale Texturen sind ein anderer Ansatz, aber ich habe sie selbst nie verwendet. iq hat in diesem Bereich viel recherchiert und einige interessante Demonstrationen auf Shadertoy veröffentlicht, so dass dies eine Möglichkeit sein könnte, zusätzliche Informationen zu sammeln.
Unabhängig davon, ob Ihre Farbe für jede Figur statisch ist, prozedural generiert oder magisch aus einer prozeduralen Textur abgetastet wurde, ist die Grundlogik dieselbe: Abstrakte Figuren in einer Art komplexem Zwischentyp (z. B. einer Struktur) speichern sowohl lokale Distanz als auch lokale Farbe in einer Instanz dieses Typs, dann übergeben Sie den komplexen Typ als Rückgabewert von Ihrer Distanzfunktion. Abhängig von Ihrer Implementierung kann die Ausgabefarbe dann direkt auf den Bildschirm übertragen werden oder dem Kollisionspunkt in Ihren Beleuchtungscode folgen.
Ich weiß nicht, ob das oben Genannte klar genug war oder nicht, also mach dir keine Sorgen, ob irgendetwas keinen Sinn ergibt. Ich kann keine GLSL / Pixel-Shading-Codebeispiele geben, da ich mit HLSL arbeite und Shading berechne, aber ich versuche gerne, alles durchzugehen, was ich überhaupt nicht richtig geschrieben habe :).