Welche Vorgehensweise bietet sich bei der Positionierung und Handhabung einer möglichst großen Anzahl von Lichtquellen in der Spielewelt an?
Die Antwort auf diese Frage ist im Prinzip ganz einfach:
Am besten geht man genauso vor wie bei der Plazierung und Handhabung der 3D-Objekte. Nirgendwo steht geschrieben, dass die in einem Vertex Buffer gespeicherten Daten lediglich die Geometrie eines 3D-Modells widerspiegeln dürfen. Aus diesem Grund führen wir eine Reihe neuer Vertex-Typen ein, die wir innerhalb der für die Beleuchtung verantwortlichen Shader-Programme als Lichtquellen interpretieren:
- struct CIlluminationDataVertex
- struct CIlluminationDataAnimatedVertex
- struct CIlluminationDataAnimatedVertex_2Skeletons
- struct CIlluminationDataAnimatedVertex_3Skeletons
- struct CIlluminationDataAnimatedVertex_4Skeletons
In Abhängigkeit von den Eigenschaften dieser „Vertex-Lichtquellen“ lassen sich nun auf einfache Weise eine Reihe von ganz unterschiedlichen Beleuchtungseffekten simulieren – wie beispielsweise (Low Frequency) Schattenwürfe oder GI-Lichteffekte (GI: Global Illumination). Welche Beleuchtungseffekte in diesem Zusammenhang genau berechnet werden sollen, können Sie mit Hilfe der Datei ApplicationSettings.txt festlegen:
GICalculationResolutionWidth: 512
GICalculationResolutionHeight: 512
ShowLowFrequencyShadows(0/1): 0
ShowAdditionalLightSources(0/1): 0
ShowAmbientLightModifiers(0/1): 0
ShowDynamicAmbientLightModifiers(0/1): 1
Verschaffen wir uns mal eine Übersicht über die einzelnen Lichtquellen-Typen, die im Zuge der Implementierung der zuvor angesprochenen Beleuchtungseffekte aktuell zum Einsatz kommen:
- 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 angesprochenen 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 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).
Download Link: VulkanFrameworkDemo2.zip