diff --git a/include/Nazara/Graphics/Config.hpp b/include/Nazara/Graphics/Config.hpp index 36a7ce6d4..a9f17a8de 100644 --- a/include/Nazara/Graphics/Config.hpp +++ b/include/Nazara/Graphics/Config.hpp @@ -29,6 +29,9 @@ /// Chaque modification d'un paramètre du module nécessite une recompilation de celui-ci +// À partir de combien d'instances d'un même mesh/matériau l'instancing doit-il être utilisé ? +#define NAZARA_GRAPHICS_INSTANCING_MIN_INSTANCES_COUNT 100 + // Utilise un tracker pour repérer les éventuels leaks (Ralentit l'exécution) #define NAZARA_GRAPHICS_MEMORYLEAKTRACKER 0 diff --git a/include/Nazara/Graphics/ForwardRenderQueue.hpp b/include/Nazara/Graphics/ForwardRenderQueue.hpp index 90a4857f3..05fa7eb53 100644 --- a/include/Nazara/Graphics/ForwardRenderQueue.hpp +++ b/include/Nazara/Graphics/ForwardRenderQueue.hpp @@ -14,6 +14,7 @@ #include #include #include +#include class NzCamera; class NzMaterial; @@ -85,7 +86,7 @@ class NAZARA_API NzForwardRenderQueue : public NzAbstractRenderQueue, NzResource typedef std::map, SkeletalMeshComparator> SkeletalMeshContainer; typedef std::map, StaticMeshComparator> StaticMeshContainer; - typedef std::map, ModelMaterialComparator> MeshContainer; + typedef std::map, ModelMaterialComparator> MeshContainer; MeshContainer opaqueModels; std::vector> transparentsModels; diff --git a/src/Nazara/Graphics/ForwardRenderQueue.cpp b/src/Nazara/Graphics/ForwardRenderQueue.cpp index 53e00c3b2..4fe55c474 100644 --- a/src/Nazara/Graphics/ForwardRenderQueue.cpp +++ b/src/Nazara/Graphics/ForwardRenderQueue.cpp @@ -136,7 +136,7 @@ void NzForwardRenderQueue::AddModel(const NzModel* model) if (pair.second) material->AddResourceListener(this, ResourceType_Material); - auto& meshMap = pair.first->second.second; + auto& meshMap = std::get<2>(pair.first->second); auto pair2 = meshMap.insert(std::make_pair(staticMesh, StaticMeshContainer::mapped_type())); if (pair2.second) @@ -144,7 +144,13 @@ void NzForwardRenderQueue::AddModel(const NzModel* model) std::vector& staticDataContainer = pair2.first->second; - staticDataContainer.resize(staticDataContainer.size()+1); + unsigned int instanceCount = staticDataContainer.size() + 1; + + // As-t-on suffisamment d'instances pour que le coût d'utilisation de l'instancing soit payé ? + if (instanceCount >= NAZARA_GRAPHICS_INSTANCING_MIN_INSTANCES_COUNT) + std::get<0>(pair.first->second) = true; // Apparemment oui, activons l'instancing avec ce matériau + + staticDataContainer.resize(instanceCount); StaticData& data = staticDataContainer.back(); data.aabb = staticMesh->GetAABB(); @@ -211,7 +217,7 @@ void NzForwardRenderQueue::OnResourceDestroy(const NzResource* resource, int ind case ResourceType_SkeletalMesh: { for (auto& pair : opaqueModels) - pair.second.first.erase(static_cast(resource)); + std::get<1>(pair.second).erase(static_cast(resource)); break; } @@ -219,7 +225,7 @@ void NzForwardRenderQueue::OnResourceDestroy(const NzResource* resource, int ind case ResourceType_StaticMesh: { for (auto& pair : opaqueModels) - pair.second.second.erase(static_cast(resource)); + std::get<2>(pair.second).erase(static_cast(resource)); break; } diff --git a/src/Nazara/Graphics/ForwardRenderTechnique.cpp b/src/Nazara/Graphics/ForwardRenderTechnique.cpp index 8d75ff24c..5db7c2aa9 100644 --- a/src/Nazara/Graphics/ForwardRenderTechnique.cpp +++ b/src/Nazara/Graphics/ForwardRenderTechnique.cpp @@ -143,20 +143,20 @@ void NzForwardRenderTechnique::Draw(const NzScene* scene) // Rendu des modèles opaques for (auto& matIt : m_renderQueue.opaqueModels) { - NzForwardRenderQueue::SkeletalMeshContainer& skeletalContainer = matIt.second.first; - NzForwardRenderQueue::StaticMeshContainer& staticContainer = matIt.second.second; + NzForwardRenderQueue::SkeletalMeshContainer& skeletalContainer = std::get<1>(matIt.second); + NzForwardRenderQueue::StaticMeshContainer& staticContainer = std::get<2>(matIt.second); if (!skeletalContainer.empty() || !staticContainer.empty()) { const NzMaterial* material = matIt.first; - // Nous utilisons de l'instancing lorsqu'aucune lumière (autre que directionnelle) n'est active + // La RenderQueue active ou non l'instancing selon le nombre d'instances + bool renderQueueInstancing = std::get<0>(matIt.second); + + // Nous utilisons de l'instancing que lorsqu'aucune lumière (autre que directionnelle) n'est active // Ceci car l'instancing n'est pas compatible avec la recherche des lumières les plus proches // (Le deferred shading n'a pas ce problème) - - ///FIXME: l'instancing fait-il réellement gagner en performances ? - ///TODO: Activer l'instancing uniquement si plusieurs instances sont à rendre ? - bool instancing = m_instancingEnabled && m_renderQueue.lights.empty(); + bool instancing = m_instancingEnabled && m_renderQueue.lights.empty() && renderQueueInstancing; // On commence par récupérer le programme du matériau const NzShaderProgram* program = material->GetShaderProgram(nzShaderTarget_Model, (instancing) ? nzShaderFlags_Instancing : 0); @@ -284,6 +284,9 @@ void NzForwardRenderTechnique::Draw(const NzScene* scene) } } } + + // Et on remet à zéro l'instancing + std::get<0>(matIt.second) = false; } for (const std::pair& pair : m_renderQueue.transparentsModels)