Vulkan-Framework-Demoprogramm 3 (Realtime Shadows)

Im Rahmen des zuletzt betrachteten Demoprogramms haben wir uns mit der
Weiterentwicklung des von uns verwendeten Beleuchtungssystems (Deferred Lighting) befasst und in diesem Zusammenhang eine Reihe von neuen Lichtquellen-Typen (sogenannte Vertex-Lichtquellen) implementiert, mit deren Hilfe sich unter anderem (Low Frequency) Schattenwürfe und verschiedenste GI-Lichteffekte (GI: Global Illumination) realisieren lassen:




  • 0 := Standard Light (Punktlicht oder Spotlight)
  • 1 := Ambient Light Modifier (In der Umgebung des betreffenden Vertex erfogt eine Modifikation des vorhandenen ambienten Lichts)
  • 2 := Light Occluder (Der betreffende Vertex fungiert als negative Lichtquelle, was zu einer Abdunklung und damit zu einem Schattenwurf führt)
  • 3 := Light Occluder (Near Distance)
  • 4 := Light Occluder (Far Distance)
  • 5 := Radiance Light (Der betreffende Vertex fungiert als Lichtquelle, sofern er selbst beleuchtet wird)
  • 6 := Dynamic Ambient Light Modifier (In der Umgebung des betreffenden Vertex erfogt eine Modifikation des vorhandenen ambienten Lichts, die davon abhängig ist, ob der Vertex im Schatten liegt oder nicht)



Die Berechnung der jeweiligen Beleuchtungseffekte erfolgt gemäß dem nachfolgend gezeigten Ablaufschema:

Rendering-Durchgang 1 (Vertex Shader):
  • Schritt 1: Verarbeitung der in einem Vertex Buffer gespeicherten Lichtquellen-Eigenschaften (Standard Light, Ambient Light Modifier, Light Occluder).
  • Schritt 2: Kopieren der Lichtquellen-Eigenschaften in zwei dafür vorgesehene Shader-Storage-Buffer-Objekte (IlluminationDataStorageBuffer, IlluminationGridStorageBuffer).


Rendering-Durchgang 2 (Vertex Shader):
  • Schritt 1: Verarbeitung der in einem Vertex Buffer gespeicherten Lichtquellen-Eigenschaften (Radiance Light, Dynamic Ambient Light Modifier), wobei ermittelt werden muss, ob und wie stark die betreffenden Vertices durch die sie umgebenden Light Occluder beschattet werden.
  • Schritt 2: Kopieren der Lichtquellen-Eigenschaften in zwei dafür vorgesehene Shader-Storage-Buffer-Objekte (IlluminationDataStorageBuffer, IlluminationGridStorageBuffer).


Rendering-Durchgang 3 (Fragment Shader):
  • Beleuchtung der Szenengeometrie (Low Frequency Schattenwürfe und GI-Lichteffekte) unter Berücksichtigung der in den Shader-Storage-Buffer-Objekten gespeicherten Lichtquellen-Eigenschaften (Deferred Lighting bei einer reduzierten Auflösung von z. B. 512*512).


Rendering-Durchgang 4 (Fragment Shader):
  • Filtern (Weichzeichnen) der im vorangegangenen Schritt berechneten Low-Resolution-Beleuchtungsdaten (Farbwerte).


Rendering-Durchgang 5 (Fragment Shader):
  • Standard-Szenenbeleuchtung (Deferred Lighting) unter Berücksichtigung der gefilterten Low-Resolution-Beleuchtungsdaten (Farbwerte).


Heute nun werden wir unser Beleuchtungssystem dahingehend erweitern, dass sich endlich auch detailliertere Schattenwürfe innerhalb einer 3D-Szene darstellen lassen. Zu diesem Zweck müssen wir zunächst einmal auf eine Reihe weiterer Rendering-Durchgänge zurückgreifen, um die dual paraboloiden Tiefenabbilder der 3D-Szene aus den jeweiligen Perspektiven der einzelnen Lichtquellen in einem weiteren Shader-Storage Buffer-Objekt zwischenzuspeichern.




Hinweise:
  • Der Raum um die Lichtquelle wird bei einer dual paraboloiden Projektion in zwei Hemisphären (Paraboloide) aufgeteilt.
  • Normalerweise werden die Tiefenabbilder aus der Lichtquellen-Perspektive als sogenannte Shadow Maps bezeichnet. Genau genommen ist diese Bezeichnung jedoch ein wenig irreführend, da in einer solchen Map (ob es sich in diesem Zusammenhang um ein Render Target oder ein Buffer-Objekt handelt, spielt keine Rolle) keine Schattenwerte sondern Abstandswerte gespeichert werden. In unseren Shader-Programmen greifen wir daher auf die allgemeinverständlichere Bezeichnung „Distance Map“ zurück.


Die eigentliche Schattenberechnung erfolgt im gleichen Fragment Shader, der auch für die Darstellung der Low Frequency Schattenwürfe und GI-Lichteffekte verantwortlich ist und basiert auf einem simplen Tiefenwert-Vergleich (Tiefenwerte aus der Kamera-Perspektive versus Tiefenwerte aus den jeweiligen Lichtquellen-Perspektiven). Zur Erklärung: Anhand der besagten Tiefenwerte wird überprüft, ob ein Szenenpixel von einer Lichtquelle aus gesehen sichtbar ist (kein Schatten) oder nicht (Schatten).


Download Link: VulkanFrameworkDemo3.zip