2 Punkte von GN⁺ 2 시간 전 | 1 Kommentare | Auf WhatsApp teilen
  • Um die interne Funktionsweise von OpenGL, Vulkan, Metal und DirectX zu verstehen, wird ein Software-Renderer ohne externe Grafikbibliotheken von Grund auf implementiert
  • Ein 3D-Modell wird aus Dreiecks-Meshes und Texturen in ein Bild umgewandelt; die Implementierung von GUI- oder GPU-Anwendungen wird dabei nicht behandelt
  • Der fertige Code umfasst etwa 500 Zeilen, und Studierende benötigen typischerweise 10 bis 20 Stunden, bis sie beginnen, einen funktionierenden Renderer zu bauen
  • Es werden nur eine TGA-Verarbeitungsklasse mit Unterstützung für RGB, RGBA und Graustufen sowie eine Funktion zum Setzen einzelner Pixel bereitgestellt; das Zeichnen von Linien und Dreiecken muss selbst implementiert werden
  • Statt den fertigen Code zu kopieren, sollte man ihn selbst schreiben, um Rendering-Konzepte zu verstehen und auch die interne Arbeitsweise von 3D-Bibliotheken nachzuvollziehen

Den Rendering-Workflow selbst aufbauen

  • Die Struktur moderner 3D-Grafikbibliotheken wird in lockerer Form nachvollzogen, um die Funktionsweise der Rendering-Pipeline zu erlernen
    • Statt zu zeigen, wie man GPU-Anwendungen schreibt, wird die interne Arbeitsweise mit einem Software-Renderer nachgebildet
    • Die Eingabe ist ein 3D-Modell aus Dreiecks-Meshes und Texturen, die Ausgabe ein gerendertes Bild
    • Ohne grafische Oberfläche erzeugt das Programm eine Bilddatei
  • Um externe Abhängigkeiten zu reduzieren, wird das einfache Bildformat TGA verwendet
    • Zu Beginn stehen nur das Laden und Speichern von Bildern sowie das Setzen der Farbe eines einzelnen Pixels zur Verfügung
    • Da es keine eingebaute Funktion zum Zeichnen von Linien oder Dreiecken gibt, muss alles selbst geschrieben werden
  • Das Startbeispiel erzeugt einen 64x64-RGB-Framebuffer, setzt die Pixel an drei Koordinaten auf Weiß und speichert ihn als framebuffer.tga
    • Farbwerte werden in der BGRA-Reihenfolge angegeben

Code bauen und ausführen

git clone https://github.com/ssloy/tinyrenderer.git &&
cd tinyrenderer &&
cmake -Bbuild &&
cmake --build build -j &&
build/tinyrenderer obj/diablo3_pose/diablo3_pose.obj obj/floor.obj
  • Das Ausführungsergebnis wird in framebuffer.tga gespeichert
  • Der fertige Code ist zwar nur etwa 500 Zeilen lang, doch der eigene Implementierungsprozess ist entscheidend für das Verständnis der Konzepte; deshalb wird nicht empfohlen, den bereitgestellten Code unverändert zu verwenden

1 Kommentare

 
GN⁺ 2 시간 전
Hacker-News-Kommentare
  • Vor ein paar Monaten habe ich einen Software-Renderer in Rust ohne LLM selbst implementiert und sogar ein einfaches Spiel sowie einen Pixelation-Shader und einen chromatischen Aberrationseffekt an den Rändern einer Taschenlampe hinzugefügt.
    https://github.com/kshitijl/tinyrenderer-rs
    Das Repository enthält viele Screenshots des Entwicklungsprozesses und lustiger visueller Bugs. Ich habe nicht nur die Rendering-Prinzipien gelernt, sondern vor allem auch, wie schnell moderne CPUs sind und dass man selbst mit einem Single-Thread-CPU-Renderer ein interaktives 3D-Spiel mit aufwendigen Spezialeffekten ausführen kann.
    • Ich frage mich, warum ein Software-Renderer von wgpu abhängt.
    • Ich frage mich, ob man beim Schreiben der Spiellogik in Rust wirklich noch ECS hinzufügen muss.
  • Dieses Material und John Vinces Mathematics for Computer Graphics waren unverzichtbar für den Bau meines Software-Renderers.
    Das war noch vor LLMs, deshalb hat es mindestens zwei Monate gedauert, und die meiste Zeit ging dafür drauf, die Mathematik der Computergrafik zu verstehen und C-Segmentation-Fehler zu verfolgen.
    • Ich frage mich, wie viele Stunden pro Tag du über mehrere Monate daran gearbeitet hast.
  • Ich frage mich, ob das Buch von Foley und Van Dam immer noch das Standardwerk auf diesem Gebiet ist. Es wurde 2013 überarbeitet, aber ich bin eher mit der Ausgabe von 1982 vertraut, die stärker auf 2D fokussiert ist; damals war das praktisch das kanonische Buch zur Computergrafik.
    • Ich habe es lange nicht mehr aufgeschlagen, und für mich ist es eher eine eigenartige Enzyklopädie mit historischem Wert.
      Diese Vorlesungsnotizen auf GitHub waren besser, um die Konzepte aufzufrischen. Den Code-Stil des Repositories mag ich nicht, und der altmodische Rasterizer ist auch zu simpel und ineffizient, aber trotzdem finde ich es lesbarer als Foleys Buch.
    • Ich habe auch mit der 2. Auflage gelernt und besitze die neueste Ausgabe von 2013; sie ist ganz ordentlich.
      Mit den Auflagen haben sich auch die verwendeten Sprachen von Pascal zu C sowie C und C++ weiterentwickelt, und in der neuesten Ausgabe ist auch etwas C# enthalten. Einige neuere Konzepte fehlen, aber ich denke, es gibt immer noch viel wertvollen Inhalt darin.
  • Ich wünschte, wenigstens ein Software-Renderer-Tutorial würde Triangle Clipping richtig behandeln. Für einen praktischen Renderer muss man das selbst in einer Basisszene zwingend handhaben, wenn Geometrie das View-Frustum schneidet, aber persönlich finde ich das am schwierigsten.
    • Dieses Thema wird in einem ganzen Kapitel behandelt: https://gabrielgambetta.com/computer-graphics-from-scratch/11-clipping.html
    • Triangle Clipping ist nur nötig, wenn Attributinterpolation bei sehr großen Dreiecken wichtig ist; es gibt zwei Wege: schnelles Verwerfen oder Primitive zusammensetzen.
      Frustum-Clipping kann über Punktauswahl in lokalen Tiles behandelt werden, und beim Zusammensetzen von Primitives ist es einfacher, mit dem invers transformierten Clipping-Rechteck in baryzentrischen Koordinaten zu arbeiten. Mit Double Precision oder Fixed-Point lassen sich Rundungsfehler kontrollieren; die zentrale Schwierigkeit ist, die Z- und 1/Z-Werte neuer Vertices neu zu erzeugen. Bei einem Rasterizer mit verzögerter Attributzusammensetzung läuft der Rest dann von selbst durch die Pipeline, und in der Open-Source-Implementierung von OpenSWR.org gibt es Beispiele.
    • Ich bin auch immer an dem Punkt hängengeblieben, an dem man „Clipping implementieren muss“, habe aber am Ende ohne große Schwierigkeiten funktionierenden Code geschrieben und erst später gemerkt, dass ich dabei den Sutherland-Hodgman-Algorithmus unabhängig neu entdeckt hatte.
      Die größte psychologische Hürde ist die Unvertrautheit mit dem projektiven Raum und homogenen Koordinaten. Die sechs Ebenen des Clip-Space sind einfach x = ±w, y = ±w, z = ±w; man geht einfach jede Polygonkante durch, bestimmt für beide Endpunkte, ob sie innen oder außen liegen, und interpoliert die Position des Grenzschnittpunkts und die Vertex-Attribute linear. Wendet man das nacheinander auf alle Ebenen an, wird das Dreieck zu einem konvexen Polygon mit höchstens 9 Vertices, das sich leicht wieder triangulieren lässt. Wenn man Outcodes im Voraus berechnet, kann man das Clipping für Dreiecke, die komplett innen oder außen liegen, überspringen.
      Paper: https://dl.acm.org/doi/10.1145/360767.360802
  • In modernen Umgebungen gibt es faktisch kein reines C++. Man kann nicht wie auf Computern der 1980er direkt in Register und VRAM schreiben, um Bildausgabe zu erzeugen; am Ende hängt man zwangsläufig auf dicken Schichten aus APIs, Treibern und Firmware und damit von einer Menge Code ab.
  • Ich versuche mich gerade aus Nostalgie für die 1990er wieder an Software-Rendering und mische 2D-artige CLUT-Bänke mit modernen Verfahren wie Scanline-Sortierung für Dreiecke und baryzentrischen Koordinaten.
    Wenn man die Form einer Fixed-Function-Pipeline beibehält, kann man mit ziemlich einfachen Zeichenfunktionen überraschend viele Dreiecke verarbeiten.
  • Ich habe einen OpenMP-Verarbeitungsbug unter macOS entdeckt und nach sehr langer Zeit meinen ersten PR in dieses Repository eingereicht.