Repository navigation
Architektur
Diese Seite zeigt, wie die Engine aufgebaut ist und was sie in den acht Bereichen der Kern-Infrastruktur (KI 1–8) im Hintergrund erledigt – zum Nachlesen neben den Aufgaben, keine Aufgabe setzt sie voraus.
sandbox.cpp die eigene Datei: SetupScene() und main(); bindet nur sandbox.h ein
Sandbox sandbox.h / sandbox_impl.cpp: die Engine, wie sandbox.cpp sie sieht – keine Vulkan-Typen
SceneObject, Camera, Light Handles auf Entities, im Besitz der Sandbox
Engine Platform (GLFW-Fenster, Eingabe-Callbacks), Renderer, ModelLoader, ImGuiSystem, die Entities
Renderer alles Vulkan: MemoryPool, ThreadPool, SwapChain, VulkanDevice
Jede Gruppe von Vulkan-Schritten ist ein Aufruf der Sandbox-Datei (NoS 1 bis NoS 6, verteilt auf die Seiten 1 bis 3 der Aufgaben). Was die Sandbox-Datei nicht erreicht, ist die Kern-Infrastruktur dieser Seite: die Vulkan-API selbst, ImGui, Descriptor Sets, die Speicherverwaltung, das Innere der Swap Chain und des Rendering-Aufbaus. Die Engine nutzt Vulkan 1.3 über vulkan.hpp (RAII-Handles, dynamischer Dispatch), durchgehend dynamic rendering und synchronization2, keine Render Passes und Framebuffers; C++20, Slang-Shader, Dear ImGui 1.92.
Die Szene besteht aus Entities; jede Entity ist eine Liste von Komponenten:
| Komponente | Inhalt |
|---|---|
TransformComponent |
Position, Rotation, Skalierung → Modellmatrix |
CameraComponent |
View- und Projektionsmatrix |
MeshComponent |
Vertices, Indizes, Instanzen, Material |
LightComponent |
Typ, Farbe, Intensität, Reichweite, Kegelwinkel; Position und Richtung kommen aus dem Transform der Entity |
TerminalCommandComponent |
wendet einmal pro Frame die getippten Terminalbefehle an |
Ein geladenes glTF-Modell wird zu einer Entity je Material (benannt <Modell>_Material_<Index>_<Materialname>), alle mit dem Transform des Objekts; Part() auf der Seite 2 Eigene Pipeline und eigene Szene spricht eine davon an.
Die Sandbox-Datei macht sechs Aufrufe je Frame (1 Initialisierungskette und Frame-Ablauf) und sieht einen Pass. Innen laufen vier: (1) die undurchsichtigen Objekte in ein Off-Screen-Farbbild; (1b) composite – dieses Bild wird mit Belichtung (exposure) und filmischem Tone Mapping auf das Swap-Chain-Bild gezeichnet; (2) die transparenten Objekte direkt auf das Swap-Chain-Bild; (3) die Bedienoberfläche der Engine. Ein Pass ist ein beginRendering … endRendering-Paar im Command Buffer mit seinen Attachments (den Bildern, in die gezeichnet wird: Farbe und Tiefe); darin werden beliebig viele Objekte mit beliebig vielen Pipelines gezeichnet. Eine eigene Pipeline zeichnet immer in Pass 1 und wird für dessen Attachments gebaut; ihre Attachments-Zeile in der Pipeline-Ansicht lautet deshalb immer off-screen color image + depth image. Die Sandbox-Datei kann keinen Pass hinzufügen.
-
Ein Rasterisierungspfad, ein Engine-Shader. Jedes Objekt, das keiner eigenen Pipeline zugewiesen ist, wird mit
pbr.slanggezeichnet (undurchsichtig, gemischt oder Glas, je nach glTF-Material). Entfernt wurden Physik, Audio, glTF-Animation, Ray Query, Forward+, planare Spiegelungen, andere Plattformen und der alte Phong-Pfad – Phong shading is something the students implement themselves. - Culling und Distanz-LOD. Ein Objekt außerhalb des Kamera-Frustums wird nicht gezeichnet; ebenso ein Objekt, dessen Hüllkugel auf weniger Pixel projiziert als eine Schwelle (Standard 1,5 px undurchsichtig, 2,5 px transparent, im Panel einstellbar). Es gibt keine LOD-Meshes, nichts wird vereinfacht. Ein kleines oder fernes Objekt, das verschwindet, ist dies und kein Fehler.
-
Laden. Ein Lade-Overlay deckt die ersten Frames ab, während Meshes und Texturen hochgeladen werden; Texturen werden auf einem Thread-Pool dekodiert; ein Watchdog bricht ab, wenn 10 s lang kein Frame fertig wird; ein Crash Reporter schreibt Minidumps nach
src/crashes/.
Je Bereich: was Vulkan verlangt, was die Engine davon übernimmt, und was davon in der Sandbox-Datei oder im Terminal noch zu sehen ist.
Vulkan verlangt die Erstellung der Instanz samt Debug Messenger und Surface, die Auswahl des physischen Geräts, das logische Gerät mit seinen Queues und die Konfiguration der Swap Chain einschließlich ihrer Neuerstellung bei einer Größenänderung des Fensters. Die Engine: InitializeWindow legt das GLFW-Fenster mit vier Eingabe-Callbacks an; CreateInstance den Dispatcher, die Instanz, den Debug Messenger und die Surface; PickDevice wählt das Gerät (Vulkan 1.3, Queue-Familien, Erweiterungen, Swap-Chain-Unterstützung, dynamicRendering; eine diskrete GPU wird bevorzugt), erzeugt das logische Gerät mit Queues und den Memory Pool; CreateSwapChain die Swap Chain mit ihren Image Views; bei Resize und wenn Acquire oder Present out of date melden, wird die Swap Chain neu erstellt. Sichtbar: die Kettenaufrufe 1–4 mit ihren [ok]-Zeilen und die Start-Logzeilen (Creating Vulkan instance... … Image views created successfully).
Anstelle von Render-Pass- und Framebuffer-Objekten nutzt die Engine das dynamic rendering von Vulkan 1.3; die Farb- und Tiefen-Attachments und die Layout-Übergänge sind vorkonfiguriert. Die Engine: InitializeRendering legt die Attachment-Beschreibungen, das Tiefenbild und die Off-Screen-Farbbilder an; jeder Pass ist ein beginRendering / endRendering-Paar; Layout-Übergänge sind explizite pipelineBarrier2-Aufrufe; Farbe wird auf Schwarz (0, 0, 0, 1) gelöscht, Tiefe auf 1,0. Sichtbar: Kettenaufruf 5; BeginRendering (clear the color and depth attachments); die Attachments-Zeile jedes Pipeline-Blocks.
Für die parallele Auslastung von CPU und GPU werden mehrere Frames gleichzeitig in Bearbeitung gehalten, mit je eigenen Command Buffers, Fences und Semaphores. Die Engine: MAX_FRAMES_IN_FLIGHT = 2; je Frame-Slot Command Buffer, image-available- und render-finished-Semaphore und eine in-flight-Fence; eine Timeline-Semaphore für Uploads. Sichtbar: Kettenaufrufe 7–8; BeginFrame wartet, bis die GPU mit dem Frame-Slot fertig ist; der Begründungstext von UpdateScene (the GPU may still be reading them).
Vulkan überlässt die Speicherverwaltung vollständig dem Entwickler. Die Engine: ein MemoryPool, von PickDevice angelegt, unterallokiert Gerätespeicher für alle Buffer und Bilder. Sichtbar: memory pool in der Beschreibung von PickDevice; Modelle und Kugeln ohne eine Zeile Buffer-Code.
Vulkan verlangt das Befüllen monolithischer Pipeline-Strukturen und VkShaderModule-Instanzen aus SPIR-V. Die Engine: CMake übersetzt beim Bauen jede src/shaders/*.slang außer den vier Modulen mit slangc -target spirv -profile spirv_1_3 und spirv-opt; zur Laufzeit lädt createShaderModule() das SPIR-V; CreatePipelines baut die eigenen Pipelines der Engine (PBR undurchsichtig / gemischt / Glas, composite); CreatePipeline macht aus der Shader-Datei und den zwei Einstellungen eine vollständige Pipeline und kopiert alles andere von der undurchsichtigen PBR-Pipeline. Sichtbar: die Pipeline-Aufrufe der Seite 2 Eigene Pipeline und eigene Szene; der Pipeline-Block mit <Datei>.slang -> <Datei>.spv; das erneute Konfigurieren nach einer neuen Shader-Datei.
Die Übersetzung der Szenendaten in den GPU-Speicher: Descriptor Pools, Layouts der Descriptor Sets, das Memory-Mapping der Uniform Buffer Objects. Die Engine: Descriptor Pool (CreateCommandBuffers), PBR-Descriptor-Set-Layouts (CreatePipelines), je Entity und Frame Uniform Buffers, dauerhaft gemappt; verzögerte Descriptor-Updates, wenn Texturen eintreffen; Materialfaktoren als Push Constants; die Lichter als Storage Buffer, jeden Frame hochgeladen. Sichtbar: die festen Shader-Eingaben mit ihren Set- und Binding-Nummern (3 Phong-Modell im Shader).
Die nativen Eingabe-Events des Windowing-Systems (GLFW) bleiben in der Engine; sie stellt eine Kamerasteuerung und ein Bedienfeld bereit. Die Engine: GLFW-Callbacks; Tasten W/↑ vor, S/↓ zurück, A/← links, D/→ rechts, Q/Bild↑ hoch, E/Bild↓ runter, linke Maustaste gedrückt dreht den Blick; Esc ist nicht belegt (Fenster schließen beendet); angewandt in UpdateScene; über einem Panel geht die Eingabe an ImGui. Das Panel Renderer: Culling & LOD (Frustum Culling, Distance LOD, zwei Schwellen, Sampler-Anisotropie, Culling-Statistik) und Tone Mapping & Tuning (Exposure, Schieberegler 0,1–4,0, Standard 1,2; der Code begrenzt nach unten auf 0,2). Sichtbar: Tasten, Maus, das Panel.
Der ganze Lebenszyklus einer Textur – Staging, Layout-Übergänge, Mipmaps, Image View, Sampler. Die Engine: libktx dekodiert auf dem Thread-Pool; Staging-Upload; sRGB- oder lineares Format; gemeinsame Standardtexturen; Descriptor-Refresh, wenn eine Textur eintrifft. Nur KTX2: ein glTF, das PNG oder JPEG referenziert, lädt seine Geometrie mit der Standard-Albedo und einer Warnung. Sichtbar: die KTX2-Regel und die Warnungen (Eigene Modelle).
Engine-Dokumentation: docs/ARCHITECTURE.md (Ownership, The initialization chain, One frame, What a mesh shader gets from the engine).