Optimisations

Former-commit-id: 81d277a49b57f061a6339678bd953054e434c613
This commit is contained in:
Lynix
2013-07-03 01:17:22 +02:00
parent 3c1c04b2aa
commit b035852576
14 changed files with 179 additions and 173 deletions

View File

@@ -124,15 +124,17 @@ void NzForwardRenderQueue::AddModel(const NzModel* model)
}
}
void NzForwardRenderQueue::Clear()
void NzForwardRenderQueue::Clear(bool fully)
{
directionnalLights.clear();
otherDrawables.clear();
visibleLights.clear();
visibleModels.clear();
visibleTransparentsModels.clear();
transparentSkeletalModels.clear();
transparentStaticModels.clear();
if (fully)
visibleModels.clear();
}
void NzForwardRenderQueue::Sort(const NzCamera& camera)
@@ -164,6 +166,11 @@ void NzForwardRenderQueue::Sort(const NzCamera& camera)
std::sort(visibleTransparentsModels.begin(), visibleTransparentsModels.end(), comparator);
}
void NzForwardRenderQueue::OnResourceDestroy(const NzResource* resource, int index)
{
}
bool NzForwardRenderQueue::SkeletalMeshComparator::operator()(const NzSkeletalMesh* subMesh1, const NzSkeletalMesh* subMesh2)
{
const NzIndexBuffer* iBuffer1 = subMesh1->GetIndexBuffer();

View File

@@ -56,104 +56,113 @@ void NzForwardRenderTechnique::Draw(const NzScene* scene)
int lightCountLocation = -1;
// Rendu des modèles opaques
for (auto matIt : m_renderQueue.visibleModels)
for (auto& matIt : m_renderQueue.visibleModels)
{
NzMaterial* material = matIt.first;
NzForwardRenderQueue::SkeletalMeshContainer& skeletalContainer = matIt.second.first;
NzForwardRenderQueue::StaticMeshContainer& staticContainer = matIt.second.second;
// On commence par récupérer le shader du matériau
const NzShader* shader;
if (material->HasCustomShader())
shader = material->GetCustomShader();
else
shader = NzShaderBuilder::Get(material->GetShaderFlags());
// Les uniformes sont conservées au sein du shader, inutile de les renvoyer tant que le shader reste le même
if (shader != lastShader)
if (!skeletalContainer.empty() || !staticContainer.empty())
{
// On récupère l'information sur l'éclairage en même temps que la position de l'uniforme "LightCount"
lightCountLocation = shader->GetUniformLocation(nzShaderUniform_LightCount);
NzMaterial* material = matIt.first;
NzRenderer::SetShader(shader);
// Couleur ambiante de la scène
shader->SendColor(shader->GetUniformLocation(nzShaderUniform_SceneAmbient), scene->GetAmbientColor());
// Position de la caméra
shader->SendVector(shader->GetUniformLocation(nzShaderUniform_CameraPosition), camera->GetPosition());
lightCount = 0;
// On envoie les lumières directionnelles s'il y a (Les mêmes pour tous)
if (lightCountLocation != -1)
{
for (const NzLight* light : m_renderQueue.directionnalLights)
{
light->Apply(shader, lightCount++);
if (lightCount > NAZARA_RENDERER_SHADER_MAX_LIGHTCOUNT)
break; // Prévenons les bêtises des utilisateurs
}
}
lastShader = shader;
}
material->Apply(shader);
// Meshs squelettiques
/*NzForwardRenderQueue::SkeletalMeshContainer& container = matIt.second.first;
if (!container.empty())
{
NzRenderer::SetVertexBuffer(m_skinningBuffer); // Vertex buffer commun
for (auto subMeshIt : container)
{
///TODO
}
}*/
// Meshs statiques
for (auto subMeshIt : matIt.second.second)
{
NzStaticMesh* mesh = subMeshIt.first;
const NzIndexBuffer* indexBuffer = mesh->GetIndexBuffer();
const NzVertexBuffer* vertexBuffer = mesh->GetVertexBuffer();
// Gestion du draw call avant la boucle de rendu
std::function<void(nzPrimitiveMode, unsigned int, unsigned int)> drawFunc;
unsigned int indexCount;
if (indexBuffer)
{
drawFunc = NzRenderer::DrawIndexedPrimitives;
indexCount = indexBuffer->GetIndexCount();
}
// On commence par récupérer le shader du matériau
const NzShader* shader;
if (material->HasCustomShader())
shader = material->GetCustomShader();
else
{
drawFunc = NzRenderer::DrawPrimitives;
indexCount = vertexBuffer->GetVertexCount();
}
shader = NzShaderBuilder::Get(material->GetShaderFlags());
NzRenderer::SetIndexBuffer(indexBuffer);
NzRenderer::SetVertexBuffer(vertexBuffer);
for (const NzMatrix4f& matrix : subMeshIt.second)
// Les uniformes sont conservées au sein du shader, inutile de les renvoyer tant que le shader reste le même
if (shader != lastShader)
{
// Calcul des lumières les plus proches
///TODO: LightManager ?
// On récupère l'information sur l'éclairage en même temps que la position de l'uniforme "LightCount"
lightCountLocation = shader->GetUniformLocation(nzShaderUniform_LightCount);
NzRenderer::SetShader(shader);
// Couleur ambiante de la scène
shader->SendColor(shader->GetUniformLocation(nzShaderUniform_SceneAmbient), scene->GetAmbientColor());
// Position de la caméra
shader->SendVector(shader->GetUniformLocation(nzShaderUniform_CameraPosition), camera->GetPosition());
lightCount = 0;
// On envoie les lumières directionnelles s'il y a (Les mêmes pour tous)
if (lightCountLocation != -1)
{
std::vector<const NzLight*>& visibleLights = m_renderQueue.visibleLights;
lightComparator.pos = matrix.GetTranslation();
std::sort(visibleLights.begin(), visibleLights.end(), lightComparator);
unsigned int max = std::min(std::min(NAZARA_RENDERER_SHADER_MAX_LIGHTCOUNT - lightCount, m_maxLightsPerObject), static_cast<unsigned int>(visibleLights.size()));
for (unsigned int i = 0; i < max; ++i)
visibleLights[i]->Apply(shader, lightCount++);
shader->SendInteger(lightCountLocation, lightCount);
for (const NzLight* light : m_renderQueue.directionnalLights)
{
light->Apply(shader, lightCount++);
if (lightCount > NAZARA_RENDERER_SHADER_MAX_LIGHTCOUNT)
break; // Prévenons les bêtises des utilisateurs
}
}
lastShader = shader;
}
NzRenderer::SetMatrix(nzMatrixType_World, matrix);
drawFunc(mesh->GetPrimitiveMode(), 0, indexCount);
material->Apply(shader);
// Meshs squelettiques
/*if (!skeletalContainer.empty())
{
NzRenderer::SetVertexBuffer(m_skinningBuffer); // Vertex buffer commun
for (auto& subMeshIt : container)
{
///TODO
}
}*/
// Meshs statiques
for (auto& subMeshIt : staticContainer)
{
NzStaticMesh* mesh = subMeshIt.first;
std::vector<NzMatrix4f>& matrices = subMeshIt.second;
if (!matrices.empty())
{
const NzIndexBuffer* indexBuffer = mesh->GetIndexBuffer();
const NzVertexBuffer* vertexBuffer = mesh->GetVertexBuffer();
// Gestion du draw call avant la boucle de rendu
std::function<void(nzPrimitiveMode, unsigned int, unsigned int)> drawFunc;
unsigned int indexCount;
if (indexBuffer)
{
drawFunc = NzRenderer::DrawIndexedPrimitives;
indexCount = indexBuffer->GetIndexCount();
}
else
{
drawFunc = NzRenderer::DrawPrimitives;
indexCount = vertexBuffer->GetVertexCount();
}
NzRenderer::SetIndexBuffer(indexBuffer);
NzRenderer::SetVertexBuffer(vertexBuffer);
for (const NzMatrix4f& matrix : matrices)
{
// Calcul des lumières les plus proches
///TODO: LightManager ?
if (lightCountLocation != -1)
{
std::vector<const NzLight*>& visibleLights = m_renderQueue.visibleLights;
lightComparator.pos = matrix.GetTranslation();
std::sort(visibleLights.begin(), visibleLights.end(), lightComparator);
unsigned int max = std::min(std::min(NAZARA_RENDERER_SHADER_MAX_LIGHTCOUNT - lightCount, m_maxLightsPerObject), static_cast<unsigned int>(visibleLights.size()));
for (unsigned int i = 0; i < max; ++i)
visibleLights[i]->Apply(shader, lightCount++);
shader->SendInteger(lightCountLocation, lightCount);
}
NzRenderer::SetMatrix(nzMatrixType_World, matrix);
drawFunc(mesh->GetPrimitiveMode(), 0, indexCount);
}
matrices.clear();
}
}
}
}

View File

@@ -115,11 +115,11 @@ namespace
bool hasTexCoords = true;
NzBufferMapper<NzVertexBuffer> vertexMapper(vertexBuffer.get(), nzBufferAccess_WriteOnly);
NzMeshVertex* meshVertices = static_cast<NzMeshVertex*>(vertexMapper.GetPointer());
for (auto uvIt : vertices)
for (auto& uvIt : vertices)
{
for (auto normalIt : uvIt.second)
for (auto& normalIt : uvIt.second)
{
for (auto positionIt : normalIt.second)
for (auto& positionIt : normalIt.second)
{
NzMeshVertex& vertex = meshVertices[positionIt.second];
@@ -261,7 +261,7 @@ namespace
specularMap.release();
}
else
NazaraWarning("Failed to load specular map (" + mtlMat->diffuseMap + ')');
NazaraWarning("Failed to load specular map (" + mtlMat->specularMap + ')');
}
// Si nous avons une alpha map ou des couleurs transparentes,

View File

@@ -151,123 +151,99 @@ bool NzMTLParser::Parse()
}
else if (keyword == "map_ka")
{
NzString map = m_currentLine.SubString(m_currentLine.GetWordPosition(1));
if (!map.IsEmpty())
unsigned int mapPos = m_currentLine.GetWordPosition(1);
if (mapPos != NzString::npos)
{
NzString map = m_currentLine.SubString(mapPos);
if (!currentMaterial)
currentMaterial = &m_materials["default"];
currentMaterial->ambientMap = map;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (keyword == "map_kd")
{
NzString map = m_currentLine.SubString(m_currentLine.GetWordPosition(1));
if (!map.IsEmpty())
unsigned int mapPos = m_currentLine.GetWordPosition(1);
if (mapPos != NzString::npos)
{
NzString map = m_currentLine.SubString(mapPos);
if (!currentMaterial)
currentMaterial = &m_materials["default"];
currentMaterial->diffuseMap = map;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (keyword == "map_ks")
{
NzString map = m_currentLine.SubString(m_currentLine.GetWordPosition(1));
if (!map.IsEmpty())
unsigned int mapPos = m_currentLine.GetWordPosition(1);
if (mapPos != NzString::npos)
{
NzString map = m_currentLine.SubString(mapPos);
if (!currentMaterial)
currentMaterial = &m_materials["default"];
currentMaterial->specularMap = map;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (keyword == "map_bump" || keyword == "bump")
{
NzString map = m_currentLine.SubString(m_currentLine.GetWordPosition(1));
if (!map.IsEmpty())
unsigned int mapPos = m_currentLine.GetWordPosition(1);
if (mapPos != NzString::npos)
{
NzString map = m_currentLine.SubString(mapPos);
if (!currentMaterial)
currentMaterial = &m_materials["default"];
currentMaterial->bumpMap = map;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (keyword == "map_d")
{
NzString map = m_currentLine.SubString(m_currentLine.GetWordPosition(1));
if (!map.IsEmpty())
unsigned int mapPos = m_currentLine.GetWordPosition(1);
if (mapPos != NzString::npos)
{
NzString map = m_currentLine.SubString(mapPos);
if (!currentMaterial)
currentMaterial = &m_materials["default"];
currentMaterial->alphaMap = map;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (keyword == "map_decal" || keyword == "decal")
{
NzString map = m_currentLine.SubString(m_currentLine.GetWordPosition(1));
if (!map.IsEmpty())
unsigned int mapPos = m_currentLine.GetWordPosition(1);
if (mapPos != NzString::npos)
{
NzString map = m_currentLine.SubString(mapPos);
if (!currentMaterial)
currentMaterial = &m_materials["default"];
currentMaterial->decalMap = map;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (keyword == "map_disp" || keyword == "disp")
{
NzString map = m_currentLine.SubString(m_currentLine.GetWordPosition(1));
if (!map.IsEmpty())
unsigned int mapPos = m_currentLine.GetWordPosition(1);
if (mapPos != NzString::npos)
{
NzString map = m_currentLine.SubString(mapPos);
if (!currentMaterial)
currentMaterial = &m_materials["default"];
currentMaterial->displacementMap = map;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (keyword == "map_refl" || keyword == "refl")
{
NzString map = m_currentLine.SubString(m_currentLine.GetWordPosition(1));
if (!map.IsEmpty())
unsigned int mapPos = m_currentLine.GetWordPosition(1);
if (mapPos != NzString::npos)
{
NzString map = m_currentLine.SubString(mapPos);
if (!currentMaterial)
currentMaterial = &m_materials["default"];
currentMaterial->reflectionMap = map;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (keyword == "newmtl")
{

View File

@@ -351,9 +351,9 @@ bool NzOBJParser::Parse()
std::unordered_map<NzString, unsigned int> materials;
unsigned int matCount = 0;
for (auto meshIt : meshes)
for (auto& meshIt : meshes)
{
for (auto matIt : meshIt.second)
for (auto& matIt : meshIt.second)
{
if (!matIt.second.empty())
{
@@ -382,8 +382,8 @@ bool NzOBJParser::Parse()
}
m_materials.resize(matCount);
for (auto it : materials)
m_materials[it.second] = it.first;
for (const std::pair<NzString, unsigned int>& pair : materials)
m_materials[pair.second] = pair.first;
return true;
}

View File

@@ -64,12 +64,12 @@ void NzScene::AddToVisibilityList(NzUpdatable* object)
void NzScene::Cull()
{
NzAbstractRenderQueue* renderQueue = m_impl->renderTechnique->GetRenderQueue();
renderQueue->Clear();
renderQueue->Clear(false);
m_impl->visibleUpdateList.clear();
// Frustum culling
RecursiveFrustumCull(renderQueue, m_impl->activeCamera->GetFrustum(), &m_impl->root);
RecursiveFrustumCull(m_impl->renderTechnique->GetRenderQueue(), m_impl->activeCamera->GetFrustum(), &m_impl->root);
///TODO: Occlusion culling