Für einfache 3D-Objekte, die nur aus nur einem einzigen Modelteil (Mesh) bestehen, ist die Implementierung von Geometry Instancing recht einfach; für komplexere 3D-Objekte, die aus mehreren Modellteilen zusammengesetzt sind, wird das Ganze schon etwas schwieriger. In diesem Zusammenhang kommt nun der Rendering Manager zum Einsatz und übernimmt das Handling aller darzustellenden 3D-Objekte.
Um die Anzahl der notwendigen Draw Calls zu reduzieren, werden die Objekte nicht mehr nacheinander gerendert; stattdessen werden die einzelnen Modellteile (Submeshes) aller Instanzen, die das gleiche 3D-Modell verwenden, nacheinander mit nur einem einzigen Renderaufruf dargestellt:
Draw Call Schema für alle Instanzen, die das gleiche 3D-Modell verwenden:
- Draw Call 1: Modelpart 1 (Instance 1, Instance 2, Instance 3, usw.)
- Draw Call 2: Modelpart 2 (Instance 1, Instance 2, Instance 3, usw.)
- Draw Call 3: Modelpart 3 (Instance 1, Instance 2, Instance 3, usw.)
- usw. (für alle Teile eines 3D-Modells)
Schritt 1: Rendering Manager initialisieren
// Rendering Manager initialisieren:
RenderingManager = new CRenderingManager;
RenderingManager->Set_NumModelsMax(10);
RenderingManager->Set_NumSkeletalAnimatedModelsMax(10);
RenderingManager->Init_MeshInstanceManager(InstancedNormalMappingShader);
RenderingManager->Init_SkeletalAnimatedMeshInstanceManager(
InstancedSkeletalAnimatedNormalMappingShader, true);
RenderingManager = new CRenderingManager;
RenderingManager->Set_NumModelsMax(10);
RenderingManager->Set_NumSkeletalAnimatedModelsMax(10);
RenderingManager->Init_MeshInstanceManager(InstancedNormalMappingShader);
RenderingManager->Init_SkeletalAnimatedMeshInstanceManager(
InstancedSkeletalAnimatedNormalMappingShader, true);
Schritt 2: die darzustellenden 3D-Modelle an den Rendering Manager übergeben
// die zu rendernden 3D-Modelle übergeben (bis zu 64 Modell-Instanzen
// können pro Modell an den Rendering Manager übergeben werden):
RenderingManager->Set_Model(TestModel1, 64);
RenderingManager->Set_Model(TestModel2, 64);
RenderingManager->Set_SkeletalAnimatedModel(SkeletalAnimatedTestModel1,
64);
// können pro Modell an den Rendering Manager übergeben werden):
RenderingManager->Set_Model(TestModel1, 64);
RenderingManager->Set_Model(TestModel2, 64);
RenderingManager->Set_SkeletalAnimatedModel(SkeletalAnimatedTestModel1,
64);
Schritt 3: verwendete Shader an den Rendering Manager binden
// Shader-Zugriff auf die in den Uniform-Buffer-Objekten gespeicherten
// Daten gewährleisten
RenderingManager->Bind_MeshDataUniformBuffer(0);
RenderingManager->Bind_MeshDataUniformBlock(InstancedNormalMappingShader);
RenderingManager->Bind_SkeletalAnimatedMeshDataUniformBuffers(1, 2, 3);
RenderingManager->Bind_SkeletalAnimatedMeshDataUniformBlocks(
InstancedSkeletalAnimatedNormalMappingShader, true);
// Daten gewährleisten
RenderingManager->Bind_MeshDataUniformBuffer(0);
RenderingManager->Bind_MeshDataUniformBlock(InstancedNormalMappingShader);
RenderingManager->Bind_SkeletalAnimatedMeshDataUniformBuffers(1, 2, 3);
RenderingManager->Bind_SkeletalAnimatedMeshDataUniformBlocks(
InstancedSkeletalAnimatedNormalMappingShader, true);
Schritt 4: Rendering Manager für die Datenaufnahme vorbereiten
RenderingManager->Reset_All_ModelInstances();
RenderingManager->Reset_All_SkeletalAnimatedModelInstances();
RenderingManager->Reset_All_SkeletalAnimatedModelInstances();
Schritt 5: Modell-Instanzen an den Rendering Manager übergeben
RenderingManager->Set_ModelInstance_For_Rendering(&TestModelInstance[0]);
RenderingManager->Set_ModelInstance_For_Rendering(&TestModelInstance[1]);
[...]
RenderingManager->Set_SkeletalAnimatedModelInstance_For_Rendering(
&TestModelInstance[8]);
RenderingManager->Set_SkeletalAnimatedModelInstance_For_Rendering(
&TestModelInstance[9]);
[...]
RenderingManager->Set_ModelInstance_For_Rendering(&TestModelInstance[1]);
[...]
RenderingManager->Set_SkeletalAnimatedModelInstance_For_Rendering(
&TestModelInstance[8]);
RenderingManager->Set_SkeletalAnimatedModelInstance_For_Rendering(
&TestModelInstance[9]);
[...]
Schritt 6: Renderfunktionen aufrufen
InstancedNormalMappingShader->Use_Shader();
Render_ManagedModels(&g_CameraPosition, &g_ViewProjectionMatrix,
RenderingManager, InstancedNormalMappingShader,
1.0f, 0);
InstancedNormalMappingShader->Stop_Using_Shader();
InstancedSkeletalAnimatedNormalMappingShader->Use_Shader();
Render_ManagedSkeletalAnimatedModels(&g_CameraPosition,
&g_ViewProjectionMatrix, RenderingManager,
InstancedSkeletalAnimatedNormalMappingShader, 0.1f, 0,
SkeletalAnimatedBody->JointTotalTransformationMatrix,
SkeletalAnimatedBody->NumJoints);
InstancedSkeletalAnimatedNormalMappingShader->Stop_Using_Shader();
Render_ManagedModels(&g_CameraPosition, &g_ViewProjectionMatrix,
RenderingManager, InstancedNormalMappingShader,
1.0f, 0);
InstancedNormalMappingShader->Stop_Using_Shader();
InstancedSkeletalAnimatedNormalMappingShader->Use_Shader();
Render_ManagedSkeletalAnimatedModels(&g_CameraPosition,
&g_ViewProjectionMatrix, RenderingManager,
InstancedSkeletalAnimatedNormalMappingShader, 0.1f, 0,
SkeletalAnimatedBody->JointTotalTransformationMatrix,
SkeletalAnimatedBody->NumJoints);
InstancedSkeletalAnimatedNormalMappingShader->Stop_Using_Shader();
Hinweise zum Erstellen eines neuen Projekts:
- Kopieren Sie den Ordner GraphicsAndPhysicsFrameworkImports ins Projektverzeichnis
- Kopieren sie alle dll-Dateien sowie die Konfigurationsdatei ResolutionAndRendering.txt aus besagtem Ordner ins gleiche Verzeichnis, in dem sich auch die exe-Datei befindet (in unseren Programmbeispielen ist dies das Bin-Verzeichnis)
- Binden Sie die folgenden Dateien in Ihr Projekt ein: GraphicsAndPhysics_Framework_Imports.h, GraphicsAndPhysics_Framework_Imports.lib, glew32.lib, glew32s.lib, glut32.lib. Die Glew- und Glut-Bibliotheken ermöglichen die Nutzung der aktuellen OpenGL-Spezifikationen unabhängig vom Framework.