Rewritted rendersystem
Former-commit-id: 9cbc601413e057047b94b8b872ee2316a86638c4
This commit is contained in:
8
src/Nazara/Graphics/AbstractRenderQueue.cpp
Normal file
8
src/Nazara/Graphics/AbstractRenderQueue.cpp
Normal file
@@ -0,0 +1,8 @@
|
||||
// Copyright (C) 2013 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Graphics/AbstractRenderQueue.hpp>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
NzAbstractRenderQueue::~NzAbstractRenderQueue() = default;
|
||||
8
src/Nazara/Graphics/AbstractRenderTechnique.cpp
Normal file
8
src/Nazara/Graphics/AbstractRenderTechnique.cpp
Normal file
@@ -0,0 +1,8 @@
|
||||
// Copyright (C) 2013 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Graphics/AbstractRenderTechnique.hpp>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
NzAbstractRenderTechnique::~NzAbstractRenderTechnique() = default;
|
||||
@@ -23,7 +23,7 @@ m_zNear(1.f)
|
||||
|
||||
NzCamera::~NzCamera() = default;
|
||||
|
||||
void NzCamera::Activate() const
|
||||
void NzCamera::Activate()
|
||||
{
|
||||
#ifdef NAZARA_GRAPHICS_SAFE
|
||||
if (!m_target)
|
||||
@@ -206,7 +206,7 @@ void NzCamera::SetZNear(float zNear)
|
||||
m_projectionMatrixUpdated = false;
|
||||
}
|
||||
|
||||
void NzCamera::AddToRenderQueue(NzRenderQueue& renderQueue) const
|
||||
void NzCamera::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const
|
||||
{
|
||||
NazaraUnused(renderQueue);
|
||||
|
||||
|
||||
224
src/Nazara/Graphics/ForwardRenderQueue.cpp
Normal file
224
src/Nazara/Graphics/ForwardRenderQueue.cpp
Normal file
@@ -0,0 +1,224 @@
|
||||
// Copyright (C) 2013 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Graphics/ForwardRenderQueue.hpp>
|
||||
#include <Nazara/Graphics/Camera.hpp>
|
||||
#include <Nazara/Graphics/Light.hpp>
|
||||
#include <Nazara/Graphics/Model.hpp>
|
||||
#include <Nazara/Renderer/Material.hpp>
|
||||
#include <Nazara/Utility/SkeletalMesh.hpp>
|
||||
#include <Nazara/Utility/StaticMesh.hpp>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
void NzForwardRenderQueue::AddDrawable(const NzDrawable* drawable)
|
||||
{
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
if (!drawable)
|
||||
{
|
||||
NazaraError("Invalid drawable");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
otherDrawables.push_back(drawable);
|
||||
}
|
||||
|
||||
void NzForwardRenderQueue::AddLight(const NzLight* light)
|
||||
{
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
if (!light)
|
||||
{
|
||||
NazaraError("Invalid light");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (light->GetLightType())
|
||||
{
|
||||
case nzLightType_Directional:
|
||||
directionnalLights.push_back(light);
|
||||
break;
|
||||
|
||||
case nzLightType_Point:
|
||||
case nzLightType_Spot:
|
||||
visibleLights.push_back(light);
|
||||
break;
|
||||
|
||||
#ifdef NAZARA_DEBUG
|
||||
default:
|
||||
NazaraError("Light type not handled (0x" + NzString::Number(light->GetLightType(), 16) + ')');
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void NzForwardRenderQueue::AddModel(const NzModel* model)
|
||||
{
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
if (!model)
|
||||
{
|
||||
NazaraError("Invalid model");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!model->IsDrawable())
|
||||
{
|
||||
NazaraError("Model is not drawable");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
const NzMatrix4f& transformMatrix = model->GetTransformMatrix();
|
||||
|
||||
NzMesh* mesh = model->GetMesh();
|
||||
unsigned int submeshCount = mesh->GetSubMeshCount();
|
||||
|
||||
for (unsigned int i = 0; i < submeshCount; ++i)
|
||||
{
|
||||
NzSubMesh* subMesh = mesh->GetSubMesh(i);
|
||||
NzMaterial* material = model->GetMaterial(subMesh->GetMaterialIndex());
|
||||
|
||||
switch (subMesh->GetAnimationType())
|
||||
{
|
||||
case nzAnimationType_Skeletal:
|
||||
{
|
||||
///TODO
|
||||
/*
|
||||
** Il y a ici deux choses importantes à gérer:
|
||||
** -Pour commencer, la mise en cache de std::vector suffisamment grands pour contenir le résultat du skinning
|
||||
** l'objectif ici est d'éviter une allocation à chaque frame, donc de réutiliser un tableau existant
|
||||
** Note: Il faudrait évaluer aussi la possibilité de conserver le buffer d'une frame à l'autre.
|
||||
** Ceci permettant de ne pas skinner inutilement ce qui ne bouge pas, ou de skinner partiellement un mesh.
|
||||
** Il faut cependant voir où stocker ce set de buffers, qui doit être communs à toutes les RQ d'une même scène.
|
||||
**
|
||||
** -Ensuite, la possibilité de regrouper les modèles skinnés identiques, une centaine de soldats marchant au pas
|
||||
** ne devrait requérir qu'un skinning.
|
||||
*/
|
||||
NazaraError("Skeletal mesh not supported yet, sorry");
|
||||
break;
|
||||
}
|
||||
|
||||
case nzAnimationType_Static:
|
||||
{
|
||||
NzStaticMesh* staticMesh = static_cast<NzStaticMesh*>(subMesh);
|
||||
if (material->IsAlphaBlendingEnabled())
|
||||
{
|
||||
unsigned int index = transparentStaticModels.size();
|
||||
transparentStaticModels.resize(index+1);
|
||||
|
||||
TransparentStaticModel& data = transparentStaticModels.back();
|
||||
data.material = material;
|
||||
data.mesh = staticMesh;
|
||||
data.transformMatrix = transformMatrix;
|
||||
|
||||
visibleTransparentsModels.push_back(std::make_pair(index, true));
|
||||
}
|
||||
else
|
||||
visibleModels[material].second[staticMesh].push_back(transformMatrix);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NzForwardRenderQueue::Clear()
|
||||
{
|
||||
directionnalLights.clear();
|
||||
otherDrawables.clear();
|
||||
visibleLights.clear();
|
||||
visibleModels.clear();
|
||||
visibleTransparentsModels.clear();
|
||||
transparentSkeletalModels.clear();
|
||||
transparentStaticModels.clear();
|
||||
}
|
||||
|
||||
void NzForwardRenderQueue::Sort(const NzCamera& camera)
|
||||
{
|
||||
struct TransparentModelComparator
|
||||
{
|
||||
bool operator()(const std::pair<unsigned int, bool>& index1, const std::pair<unsigned int, bool>& index2)
|
||||
{
|
||||
const NzMatrix4f& matrix1 = (index1.second) ?
|
||||
queue->transparentStaticModels[index1.first].transformMatrix :
|
||||
queue->transparentSkeletalModels[index1.first].transformMatrix;
|
||||
|
||||
const NzMatrix4f& matrix2 = (index1.second) ?
|
||||
queue->transparentStaticModels[index2.first].transformMatrix :
|
||||
queue->transparentSkeletalModels[index2.first].transformMatrix;
|
||||
|
||||
return nearPlane.Distance(matrix1.GetTranslation()) < nearPlane.Distance(matrix2.GetTranslation());
|
||||
}
|
||||
|
||||
NzForwardRenderQueue* queue;
|
||||
NzPlanef nearPlane;
|
||||
};
|
||||
|
||||
TransparentModelComparator comparator {this, camera.GetFrustum().GetPlane(nzFrustumPlane_Near)};
|
||||
std::sort(visibleTransparentsModels.begin(), visibleTransparentsModels.end(), comparator);
|
||||
}
|
||||
|
||||
bool NzForwardRenderQueue::SkeletalMeshComparator::operator()(const NzSkeletalMesh* subMesh1, const NzSkeletalMesh* subMesh2)
|
||||
{
|
||||
const NzIndexBuffer* iBuffer1 = subMesh1->GetIndexBuffer();
|
||||
const NzBuffer* buffer1 = (iBuffer1) ? iBuffer1->GetBuffer() : nullptr;
|
||||
|
||||
const NzIndexBuffer* iBuffer2 = subMesh1->GetIndexBuffer();
|
||||
const NzBuffer* buffer2 = (iBuffer2) ? iBuffer2->GetBuffer() : nullptr;
|
||||
|
||||
if (buffer1 == buffer2)
|
||||
return subMesh1 < subMesh2;
|
||||
else
|
||||
return buffer2 < buffer2;
|
||||
}
|
||||
|
||||
bool NzForwardRenderQueue::StaticMeshComparator::operator()(const NzStaticMesh* subMesh1, const NzStaticMesh* subMesh2)
|
||||
{
|
||||
const NzIndexBuffer* iBuffer1 = subMesh1->GetIndexBuffer();
|
||||
const NzBuffer* buffer1 = (iBuffer1) ? iBuffer1->GetBuffer() : nullptr;
|
||||
|
||||
const NzIndexBuffer* iBuffer2 = subMesh1->GetIndexBuffer();
|
||||
const NzBuffer* buffer2 = (iBuffer2) ? iBuffer2->GetBuffer() : nullptr;
|
||||
|
||||
if (buffer1 == buffer2)
|
||||
{
|
||||
buffer1 = subMesh1->GetVertexBuffer()->GetBuffer();
|
||||
buffer2 = subMesh2->GetVertexBuffer()->GetBuffer();
|
||||
|
||||
if (buffer1 == buffer2)
|
||||
return subMesh1 < subMesh2;
|
||||
else
|
||||
return buffer1 < buffer2;
|
||||
}
|
||||
else
|
||||
return buffer1 < buffer2;
|
||||
}
|
||||
|
||||
bool NzForwardRenderQueue::MaterialComparator::operator()(const NzMaterial* mat1, const NzMaterial* mat2)
|
||||
{
|
||||
const NzShader* shader1 = mat1->GetCustomShader();
|
||||
const NzShader* shader2 = mat2->GetCustomShader();
|
||||
|
||||
if (shader1)
|
||||
{
|
||||
if (shader2)
|
||||
{
|
||||
if (shader1 != shader2)
|
||||
return shader1 < shader2;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
else if (shader2)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
nzUInt32 shaderFlags1 = mat1->GetShaderFlags();
|
||||
nzUInt32 shaderFlags2 = mat2->GetShaderFlags();
|
||||
|
||||
if (shaderFlags1 != shaderFlags2)
|
||||
return shaderFlags1 < shaderFlags2;
|
||||
}
|
||||
|
||||
return mat1 < mat2;
|
||||
}
|
||||
277
src/Nazara/Graphics/ForwardRenderTechnique.cpp
Normal file
277
src/Nazara/Graphics/ForwardRenderTechnique.cpp
Normal file
@@ -0,0 +1,277 @@
|
||||
// Copyright (C) 2013 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Graphics/ForwardRenderTechnique.hpp>
|
||||
#include <Nazara/Graphics/Background.hpp>
|
||||
#include <Nazara/Graphics/Camera.hpp>
|
||||
#include <Nazara/Graphics/Drawable.hpp>
|
||||
#include <Nazara/Graphics/Light.hpp>
|
||||
#include <Nazara/Renderer/Config.hpp>
|
||||
#include <Nazara/Renderer/Material.hpp>
|
||||
#include <Nazara/Renderer/Renderer.hpp>
|
||||
#include <Nazara/Renderer/ShaderBuilder.hpp>
|
||||
#include <Nazara/Utility/StaticMesh.hpp>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
struct LightComparator
|
||||
{
|
||||
bool operator()(const NzLight* light1, const NzLight* light2)
|
||||
{
|
||||
return light1->GetPosition().SquaredDistance(pos) < light2->GetPosition().SquaredDistance(pos);
|
||||
}
|
||||
|
||||
NzVector3f pos;
|
||||
};
|
||||
}
|
||||
|
||||
NzForwardRenderTechnique::NzForwardRenderTechnique() :
|
||||
m_maxLightsPerObject(3) // Valeur totalement arbitraire
|
||||
{
|
||||
}
|
||||
|
||||
void NzForwardRenderTechnique::Clear(const NzScene* scene)
|
||||
{
|
||||
NzRenderer::Enable(nzRendererParameter_DepthBuffer, true);
|
||||
NzRenderer::Enable(nzRendererParameter_DepthWrite, true);
|
||||
NzRenderer::Clear(nzRendererClear_Depth);
|
||||
|
||||
NzBackground* background = scene->GetBackground();
|
||||
if (background)
|
||||
background->Draw(scene);
|
||||
}
|
||||
|
||||
void NzForwardRenderTechnique::Draw(const NzScene* scene)
|
||||
{
|
||||
///TODO: Regrouper les activations par méthode
|
||||
LightComparator lightComparator;
|
||||
|
||||
const NzCamera* camera = scene->GetActiveCamera();
|
||||
const NzShader* lastShader = nullptr;
|
||||
|
||||
// Externes à la boucle pour conserver leur valeurs si le shader ne change pas
|
||||
unsigned int lightCount = 0;
|
||||
int lightCountLocation = -1;
|
||||
|
||||
// Rendu des modèles opaques
|
||||
for (auto matIt : m_renderQueue.visibleModels)
|
||||
{
|
||||
NzMaterial* material = matIt.first;
|
||||
|
||||
// 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)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
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();
|
||||
}
|
||||
else
|
||||
{
|
||||
drawFunc = NzRenderer::DrawPrimitives;
|
||||
indexCount = vertexBuffer->GetVertexCount();
|
||||
}
|
||||
|
||||
NzRenderer::SetIndexBuffer(indexBuffer);
|
||||
NzRenderer::SetVertexBuffer(vertexBuffer);
|
||||
|
||||
for (const NzMatrix4f& matrix : subMeshIt.second)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const std::pair<unsigned int, bool>& pair : m_renderQueue.visibleTransparentsModels)
|
||||
{
|
||||
// Matériau
|
||||
NzMaterial* material = (pair.second) ?
|
||||
m_renderQueue.transparentStaticModels[pair.first].material :
|
||||
m_renderQueue.transparentSkeletalModels[pair.first].material;
|
||||
|
||||
// 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)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
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);
|
||||
|
||||
// Mesh
|
||||
if (pair.second)
|
||||
{
|
||||
NzForwardRenderQueue::TransparentStaticModel& staticModel = m_renderQueue.transparentStaticModels[pair.first];
|
||||
|
||||
const NzMatrix4f& matrix = staticModel.transformMatrix;
|
||||
NzStaticMesh* mesh = staticModel.mesh;
|
||||
|
||||
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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
///TODO
|
||||
}
|
||||
}
|
||||
|
||||
// Les autres drawables (Exemple: Terrain)
|
||||
for (const NzDrawable* drawable : m_renderQueue.otherDrawables)
|
||||
drawable->Draw();
|
||||
}
|
||||
|
||||
unsigned int NzForwardRenderTechnique::GetMaxLightsPerObject() const
|
||||
{
|
||||
return m_maxLightsPerObject;
|
||||
}
|
||||
|
||||
NzAbstractRenderQueue* NzForwardRenderTechnique::GetRenderQueue()
|
||||
{
|
||||
return &m_renderQueue;
|
||||
}
|
||||
|
||||
void NzForwardRenderTechnique::SetMaxLightsPerObject(unsigned int lightCount)
|
||||
{
|
||||
m_maxLightsPerObject = lightCount;
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <Nazara/Graphics/Light.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Graphics/AbstractRenderQueue.hpp>
|
||||
#include <Nazara/Math/Basic.hpp>
|
||||
#include <Nazara/Math/Sphere.hpp>
|
||||
#include <Nazara/Renderer/Renderer.hpp>
|
||||
@@ -32,23 +33,9 @@ NzSceneNode(light)
|
||||
std::memcpy(this, &light, sizeof(NzLight)); // Aussi simple que ça
|
||||
}
|
||||
|
||||
NzLight::~NzLight()
|
||||
void NzLight::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const
|
||||
{
|
||||
}
|
||||
|
||||
void NzLight::AddToRenderQueue(NzRenderQueue& renderQueue) const
|
||||
{
|
||||
switch (m_type)
|
||||
{
|
||||
case nzLightType_Directional:
|
||||
renderQueue.directionnalLights.push_back(this);
|
||||
break;
|
||||
|
||||
case nzLightType_Point:
|
||||
case nzLightType_Spot:
|
||||
renderQueue.visibleLights.push_back(this);
|
||||
break;
|
||||
}
|
||||
renderQueue->AddLight(this);
|
||||
}
|
||||
|
||||
void NzLight::Apply(const NzShader* shader, unsigned int lightUnit) const
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Graphics/Model.hpp>
|
||||
#include <Nazara/Graphics/AbstractRenderQueue.hpp>
|
||||
#include <Nazara/Graphics/Config.hpp>
|
||||
#include <Nazara/Utility/SkeletalMesh.hpp>
|
||||
#include <Nazara/Utility/StaticMesh.hpp>
|
||||
@@ -64,45 +65,9 @@ NzModel::~NzModel()
|
||||
Reset();
|
||||
}
|
||||
|
||||
void NzModel::AddToRenderQueue(NzRenderQueue& renderQueue) const
|
||||
void NzModel::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const
|
||||
{
|
||||
if (!m_transformMatrixUpdated)
|
||||
UpdateTransformMatrix();
|
||||
|
||||
unsigned int subMeshCount = m_mesh->GetSubMeshCount();
|
||||
for (unsigned int i = 0; i < subMeshCount; ++i)
|
||||
{
|
||||
NzSubMesh* subMesh = m_mesh->GetSubMesh(i);
|
||||
NzMaterial* material = m_materials[m_skin*m_matCount + subMesh->GetMaterialIndex()];
|
||||
|
||||
switch (subMesh->GetAnimationType())
|
||||
{
|
||||
case nzAnimationType_Skeletal:
|
||||
{
|
||||
NzSkeletalMesh* skeletalMesh = static_cast<NzSkeletalMesh*>(subMesh);
|
||||
std::vector<NzRenderQueue::SkeletalData>& data = renderQueue.visibleSkeletalModels[material][skeletalMesh];
|
||||
|
||||
///TODO: Corriger cette abomination
|
||||
data.resize(data.size()+1);
|
||||
NzRenderQueue::SkeletalData& skeletalData = data.back();
|
||||
|
||||
skeletalData.skinnedVertices.resize(skeletalMesh->GetVertexCount());
|
||||
skeletalData.transformMatrix = m_transformMatrix;
|
||||
|
||||
skeletalMesh->Skin(&skeletalData.skinnedVertices[0], &m_skeleton);
|
||||
break;
|
||||
}
|
||||
|
||||
case nzAnimationType_Static:
|
||||
{
|
||||
NzStaticMesh* staticMesh = static_cast<NzStaticMesh*>(subMesh);
|
||||
std::vector<NzMatrix4f>& matrices = renderQueue.visibleStaticModels[material][staticMesh];
|
||||
|
||||
matrices.push_back(m_transformMatrix);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
renderQueue->AddModel(this);
|
||||
}
|
||||
|
||||
void NzModel::AdvanceAnimation(float elapsedTime)
|
||||
@@ -310,6 +275,11 @@ bool NzModel::IsAnimationEnabled() const
|
||||
return m_animationEnabled;
|
||||
}
|
||||
|
||||
bool NzModel::IsDrawable() const
|
||||
{
|
||||
return m_mesh != nullptr && m_mesh->GetSubMeshCount() >= 1;
|
||||
}
|
||||
|
||||
bool NzModel::IsDrawEnabled() const
|
||||
{
|
||||
return m_drawEnabled;
|
||||
@@ -702,9 +672,9 @@ void NzModel::UpdateBoundingBox() const
|
||||
bool NzModel::VisibilityTest(const NzFrustumf& frustum)
|
||||
{
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
if (!m_mesh)
|
||||
if (!IsDrawable())
|
||||
{
|
||||
NazaraError("Model has no mesh");
|
||||
NazaraError("Model is not drawable");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
// Copyright (C) 2013 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Graphics/RenderQueue.hpp>
|
||||
#include <Nazara/Renderer/Material.hpp>
|
||||
#include <Nazara/Utility/SkeletalMesh.hpp>
|
||||
#include <Nazara/Utility/StaticMesh.hpp>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
bool NzRenderQueue::MaterialComparator::operator()(const NzMaterial* mat1, const NzMaterial* mat2)
|
||||
{
|
||||
const NzShader* shader1 = mat1->GetCustomShader();
|
||||
const NzShader* shader2 = mat2->GetCustomShader();
|
||||
|
||||
if (shader1)
|
||||
{
|
||||
if (shader2)
|
||||
return shader1 < shader2;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
else if (shader2)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
nzUInt32 shaderFlags1 = mat1->GetShaderFlags();
|
||||
nzUInt32 shaderFlags2 = mat2->GetShaderFlags();
|
||||
|
||||
if (shaderFlags1 == shaderFlags2)
|
||||
return mat1 < mat2;
|
||||
else
|
||||
return shaderFlags1 < shaderFlags2;
|
||||
}
|
||||
}
|
||||
|
||||
bool NzRenderQueue::SkeletalMeshComparator::operator()(const NzSkeletalMesh* subMesh1, const NzSkeletalMesh* subMesh2)
|
||||
{
|
||||
const NzBuffer* buffer1;
|
||||
const NzIndexBuffer* iBuffer1 = subMesh1->GetIndexBuffer();
|
||||
if (iBuffer1)
|
||||
buffer1 = iBuffer1->GetBuffer();
|
||||
else
|
||||
buffer1 = nullptr;
|
||||
|
||||
const NzBuffer* buffer2;
|
||||
const NzIndexBuffer* iBuffer2 = subMesh1->GetIndexBuffer();
|
||||
if (iBuffer2)
|
||||
buffer2 = iBuffer1->GetBuffer();
|
||||
else
|
||||
buffer2 = nullptr;
|
||||
|
||||
if (buffer1 == buffer2)
|
||||
return subMesh1 < subMesh2;
|
||||
else
|
||||
return buffer2 < buffer2;
|
||||
}
|
||||
|
||||
bool NzRenderQueue::StaticMeshComparator::operator()(const NzStaticMesh* subMesh1, const NzStaticMesh* subMesh2)
|
||||
{
|
||||
const NzBuffer* buffer1;
|
||||
const NzIndexBuffer* iBuffer1 = subMesh1->GetIndexBuffer();
|
||||
if (iBuffer1)
|
||||
buffer1 = iBuffer1->GetBuffer();
|
||||
else
|
||||
buffer1 = nullptr;
|
||||
|
||||
const NzBuffer* buffer2;
|
||||
const NzIndexBuffer* iBuffer2 = subMesh1->GetIndexBuffer();
|
||||
if (iBuffer2)
|
||||
buffer2 = iBuffer1->GetBuffer();
|
||||
else
|
||||
buffer2 = nullptr;
|
||||
|
||||
if (iBuffer1 == iBuffer2)
|
||||
{
|
||||
buffer1 = subMesh1->GetVertexBuffer()->GetBuffer();
|
||||
buffer2 = subMesh2->GetVertexBuffer()->GetBuffer();
|
||||
|
||||
if (buffer1 == buffer2)
|
||||
return subMesh1 < subMesh2;
|
||||
else
|
||||
return buffer1 < buffer2;
|
||||
}
|
||||
else
|
||||
return iBuffer1 < iBuffer2;
|
||||
}
|
||||
|
||||
void NzRenderQueue::Clear()
|
||||
{
|
||||
directionnalLights.clear();
|
||||
otherDrawables.clear();
|
||||
visibleLights.clear();
|
||||
visibleSkeletalModels.clear();
|
||||
visibleStaticModels.clear();
|
||||
}
|
||||
@@ -5,41 +5,17 @@
|
||||
#include <Nazara/Graphics/Scene.hpp>
|
||||
#include <Nazara/Core/Clock.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Graphics/ColorBackground.hpp>
|
||||
#include <Nazara/Graphics/Drawable.hpp>
|
||||
#include <Nazara/Graphics/Camera.hpp>
|
||||
#include <Nazara/Graphics/Light.hpp>
|
||||
#include <Nazara/Graphics/Model.hpp>
|
||||
#include <Nazara/Graphics/RenderQueue.hpp>
|
||||
#include <Nazara/Graphics/ColorBackground.hpp>
|
||||
#include <Nazara/Graphics/ForwardRenderTechnique.hpp>
|
||||
#include <Nazara/Graphics/SceneRoot.hpp>
|
||||
#include <Nazara/Renderer/Config.hpp>
|
||||
#include <Nazara/Renderer/Renderer.hpp>
|
||||
#include <Nazara/Renderer/Shader.hpp>
|
||||
#include <Nazara/Renderer/ShaderBuilder.hpp>
|
||||
#include <Nazara/Utility/BufferMapper.hpp>
|
||||
#include <Nazara/Utility/SkeletalMesh.hpp>
|
||||
#include <Nazara/Utility/StaticMesh.hpp>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
const unsigned int maxLights = 8; ///TODO: Config
|
||||
|
||||
struct LightComparator
|
||||
{
|
||||
bool operator()(const NzLight* light1, const NzLight* light2)
|
||||
{
|
||||
return light1->GetPosition().SquaredDistance(pos) < light2->GetPosition().SquaredDistance(pos);
|
||||
}
|
||||
|
||||
NzVector3f pos;
|
||||
};
|
||||
}
|
||||
|
||||
struct NzSceneImpl
|
||||
{
|
||||
NzSceneImpl(NzScene* scene) :
|
||||
@@ -47,16 +23,14 @@ struct NzSceneImpl
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<NzAbstractRenderTechnique> renderTechnique;
|
||||
std::unique_ptr<NzBackground> background;
|
||||
std::vector<NzUpdatable*> updateList;
|
||||
std::vector<NzUpdatable*> visibleUpdateList;
|
||||
std::vector<NzRenderer::InstancingData> instancingData;
|
||||
NzClock updateClock;
|
||||
NzColor ambientColor = NzColor(25,25,25);
|
||||
NzRenderQueue renderQueue;
|
||||
NzSceneRoot root;
|
||||
const NzCamera* activeCamera;
|
||||
NzVertexBuffer* skinningBuffer;
|
||||
NzCamera* activeCamera;
|
||||
bool update;
|
||||
float frameTime;
|
||||
float updateTime;
|
||||
@@ -67,10 +41,7 @@ NzScene::NzScene()
|
||||
{
|
||||
m_impl = new NzSceneImpl(this);
|
||||
m_impl->background.reset(new NzColorBackground);
|
||||
m_impl->skinningBuffer = new NzVertexBuffer(NzMesh::GetDeclaration(), 20000, nzBufferStorage_Hardware, nzBufferUsage_Dynamic);
|
||||
|
||||
if (NzRenderer::HasCapability(nzRendererCap_Instancing))
|
||||
m_impl->instancingData.resize(NAZARA_RENDERER_INSTANCING_MAX);
|
||||
m_impl->renderTechnique.reset(new NzForwardRenderTechnique);
|
||||
}
|
||||
|
||||
NzScene::~NzScene()
|
||||
@@ -81,7 +52,6 @@ NzScene::~NzScene()
|
||||
static_cast<NzSceneNode*>(child)->SetScene(nullptr);
|
||||
}
|
||||
|
||||
delete m_impl->skinningBuffer;
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
@@ -92,11 +62,13 @@ void NzScene::AddToVisibilityList(NzUpdatable* object)
|
||||
|
||||
void NzScene::Cull()
|
||||
{
|
||||
m_impl->renderQueue.Clear();
|
||||
NzAbstractRenderQueue* renderQueue = m_impl->renderTechnique->GetRenderQueue();
|
||||
renderQueue->Clear();
|
||||
|
||||
m_impl->visibleUpdateList.clear();
|
||||
|
||||
// Frustum culling
|
||||
RecursiveFrustumCull(m_impl->renderQueue, m_impl->activeCamera->GetFrustum(), &m_impl->root);
|
||||
RecursiveFrustumCull(renderQueue, m_impl->activeCamera->GetFrustum(), &m_impl->root);
|
||||
|
||||
///TODO: Occlusion culling
|
||||
|
||||
@@ -105,234 +77,30 @@ void NzScene::Cull()
|
||||
|
||||
void NzScene::Draw()
|
||||
{
|
||||
NzRenderer::Clear(nzRendererClear_Depth);
|
||||
|
||||
if (m_impl->background)
|
||||
m_impl->background->Draw(this);
|
||||
|
||||
LightComparator lightComparator;
|
||||
|
||||
// Pour les meshs squelettiques, on utilise un buffer commun
|
||||
NzRenderer::SetVertexBuffer(m_impl->skinningBuffer);
|
||||
for (auto matIt : m_impl->renderQueue.visibleSkeletalModels)
|
||||
{
|
||||
// On applique le shader du matériau
|
||||
nzUInt32 shaderFlags = matIt.first->GetShaderFlags();
|
||||
|
||||
const NzShader* shader = NzShaderBuilder::Get(shaderFlags);
|
||||
|
||||
NzRenderer::SetShader(shader);
|
||||
matIt.first->Apply(shader);
|
||||
|
||||
// Position de la caméra
|
||||
int camPosLocation = shader->GetUniformLocation(nzShaderUniform_CameraPosition);
|
||||
if (camPosLocation != -1)
|
||||
shader->SendVector(camPosLocation, m_impl->activeCamera->GetPosition());
|
||||
|
||||
// Couleur ambiante de la scène
|
||||
int sceneAmbientLocation = shader->GetUniformLocation(nzShaderUniform_SceneAmbient);
|
||||
if (sceneAmbientLocation != -1)
|
||||
shader->SendColor(sceneAmbientLocation, m_impl->ambientColor);
|
||||
|
||||
// Gestion des lumières (D'abord directionnelles)
|
||||
int lightCountLocation = shader->GetUniformLocation(nzShaderUniform_LightCount);
|
||||
|
||||
unsigned int lightIndex = 0;
|
||||
if (lightCountLocation != -1)
|
||||
{
|
||||
for (const NzLight* light : m_impl->renderQueue.directionnalLights)
|
||||
{
|
||||
light->Apply(shader, lightIndex++);
|
||||
if (lightIndex > maxLights)
|
||||
break; // N'arrivera jamais mais pourrait résulter en un bug
|
||||
}
|
||||
}
|
||||
|
||||
for (auto subMeshIt : matIt.second)
|
||||
{
|
||||
const NzSkeletalMesh* skeletalMesh = subMeshIt.first;
|
||||
const NzIndexBuffer* indexBuffer = skeletalMesh->GetIndexBuffer();
|
||||
|
||||
unsigned int vertexCount = skeletalMesh->GetVertexCount();
|
||||
|
||||
// Gestion du draw call avant la boucle de rendu
|
||||
std::function<void(nzPrimitiveType, unsigned int, unsigned int)> drawFunc;
|
||||
nzPrimitiveType primitiveType = skeletalMesh->GetPrimitiveType();
|
||||
unsigned int indexCount;
|
||||
if (indexBuffer)
|
||||
{
|
||||
drawFunc = NzRenderer::DrawIndexedPrimitives;
|
||||
indexCount = indexBuffer->GetIndexCount();
|
||||
NzRenderer::SetIndexBuffer(indexBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
drawFunc = NzRenderer::DrawPrimitives;
|
||||
indexCount = skeletalMesh->GetVertexCount();
|
||||
}
|
||||
|
||||
for (const NzRenderQueue::SkeletalData& data : subMeshIt.second)
|
||||
{
|
||||
// Transfert du résultat du skinning vers notre buffer hardware
|
||||
NzBufferMapper<NzVertexBuffer> outputMapper(m_impl->skinningBuffer, nzBufferAccess_DiscardAndWrite, 0, vertexCount);
|
||||
std::memcpy(outputMapper.GetPointer(), &data.skinnedVertices[0], vertexCount*sizeof(NzMeshVertex));
|
||||
outputMapper.Unmap();
|
||||
|
||||
// Calcul des lumières les plus proches (TODO: LightManager ?)
|
||||
if (lightCountLocation != -1)
|
||||
{
|
||||
auto visibleLights = m_impl->renderQueue.visibleLights;
|
||||
lightComparator.pos = data.transformMatrix.GetTranslation();
|
||||
std::sort(visibleLights.begin(), visibleLights.end(), lightComparator);
|
||||
|
||||
const unsigned int maxLightPerObject = 3; ///TODO: Config
|
||||
unsigned int max = std::min(std::min(maxLights - lightIndex, maxLightPerObject), static_cast<unsigned int>(visibleLights.size()));
|
||||
for (unsigned int i = 0; i < max; ++i)
|
||||
visibleLights[i]->Apply(shader, lightIndex + i);
|
||||
|
||||
shader->SendInteger(lightCountLocation, lightIndex + max);
|
||||
}
|
||||
|
||||
NzRenderer::SetMatrix(nzMatrixType_World, data.transformMatrix);
|
||||
|
||||
drawFunc(primitiveType, 0, indexCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pour les meshs statiques, on utilise le buffer du mesh
|
||||
for (auto matIt : m_impl->renderQueue.visibleStaticModels)
|
||||
{
|
||||
// On applique le shader du matériau
|
||||
nzUInt32 shaderFlags = matIt.first->GetShaderFlags();
|
||||
if (NzRenderer::HasCapability(nzRendererCap_Instancing) && m_impl->renderQueue.visibleLights.empty())
|
||||
shaderFlags |= nzShaderFlags_Instancing;
|
||||
|
||||
const NzShader* shader = NzShaderBuilder::Get(shaderFlags);
|
||||
|
||||
NzRenderer::SetShader(shader);
|
||||
matIt.first->Apply(shader);
|
||||
|
||||
bool instancing = shader->GetFlags() & nzShaderFlags_Instancing;
|
||||
|
||||
// Position de la caméra
|
||||
int camPosLocation = shader->GetUniformLocation(nzShaderUniform_CameraPosition);
|
||||
if (camPosLocation != -1)
|
||||
shader->SendVector(camPosLocation, m_impl->activeCamera->GetPosition());
|
||||
|
||||
// Couleur ambiante de la scène
|
||||
int sceneAmbientLocation = shader->GetUniformLocation(nzShaderUniform_SceneAmbient);
|
||||
if (sceneAmbientLocation != -1)
|
||||
shader->SendColor(sceneAmbientLocation, m_impl->ambientColor);
|
||||
|
||||
// Gestion des lumières (D'abord directionnelles)
|
||||
int lightCountLocation = shader->GetUniformLocation(nzShaderUniform_LightCount);
|
||||
|
||||
unsigned int lightIndex = 0;
|
||||
if (lightCountLocation != -1)
|
||||
{
|
||||
for (const NzLight* light : m_impl->renderQueue.directionnalLights)
|
||||
{
|
||||
light->Apply(shader, lightIndex++);
|
||||
if (lightIndex > maxLights)
|
||||
break; // N'arrivera probablement jamais mais pourrait résulter en un bug
|
||||
}
|
||||
}
|
||||
|
||||
for (auto subMeshIt : matIt.second)
|
||||
{
|
||||
NzStaticMesh* staticMesh = subMeshIt.first;
|
||||
|
||||
const NzIndexBuffer* indexBuffer = staticMesh->GetIndexBuffer();
|
||||
const NzVertexBuffer* vertexBuffer = staticMesh->GetVertexBuffer();
|
||||
|
||||
NzRenderer::SetVertexBuffer(vertexBuffer);
|
||||
|
||||
// Gestion du draw call avant la boucle de rendu
|
||||
std::function<void(nzPrimitiveType, unsigned int, unsigned int)> draw;
|
||||
std::function<void(unsigned int, nzPrimitiveType, unsigned int, unsigned int)> instancedDraw;
|
||||
nzPrimitiveType primitiveType = staticMesh->GetPrimitiveType();
|
||||
unsigned int indexCount;
|
||||
if (indexBuffer)
|
||||
{
|
||||
draw = NzRenderer::DrawIndexedPrimitives;
|
||||
indexCount = indexBuffer->GetIndexCount();
|
||||
instancedDraw = NzRenderer::DrawIndexedPrimitivesInstanced;
|
||||
NzRenderer::SetIndexBuffer(indexBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
draw = NzRenderer::DrawPrimitives;
|
||||
indexCount = vertexBuffer->GetVertexCount();
|
||||
instancedDraw = NzRenderer::DrawPrimitivesInstanced;
|
||||
}
|
||||
|
||||
if (instancing)
|
||||
{
|
||||
if (lightCountLocation != -1)
|
||||
shader->SendInteger(lightCountLocation, lightIndex);
|
||||
|
||||
unsigned int count = 0;
|
||||
for (const NzMatrix4f& matrix : subMeshIt.second)
|
||||
{
|
||||
m_impl->instancingData[count++].worldMatrix = matrix;
|
||||
if (count == m_impl->instancingData.size())
|
||||
{
|
||||
NzRenderer::SetInstancingData(&m_impl->instancingData[0], count);
|
||||
instancedDraw(count, primitiveType, 0, indexCount);
|
||||
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
NzRenderer::SetInstancingData(&m_impl->instancingData[0], count);
|
||||
instancedDraw(count, primitiveType, 0, indexCount);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const NzMatrix4f& matrix : subMeshIt.second)
|
||||
{
|
||||
// Calcul des lumières les plus proches (TODO: LightManager ?)
|
||||
if (lightCountLocation != -1)
|
||||
{
|
||||
std::vector<const NzLight*>& visibleLights = m_impl->renderQueue.visibleLights;
|
||||
lightComparator.pos = matrix.GetTranslation();
|
||||
std::sort(visibleLights.begin(), visibleLights.end(), lightComparator);
|
||||
|
||||
const unsigned int maxLightPerObject = 3; ///TODO: Config
|
||||
unsigned int max = std::min(std::min(maxLights - lightIndex, maxLightPerObject), static_cast<unsigned int>(visibleLights.size()));
|
||||
for (unsigned int i = 0; i < max; ++i)
|
||||
visibleLights[i]->Apply(shader, lightIndex + i);
|
||||
|
||||
shader->SendInteger(lightCountLocation, lightIndex + max);
|
||||
}
|
||||
|
||||
NzRenderer::SetMatrix(nzMatrixType_World, matrix);
|
||||
|
||||
draw(primitiveType, 0, indexCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Les autres drawables (Exemple: Terrain)
|
||||
for (const NzDrawable* drawable : m_impl->renderQueue.otherDrawables)
|
||||
drawable->Draw();
|
||||
m_impl->renderTechnique->Clear(this);
|
||||
m_impl->renderTechnique->Draw(this);
|
||||
}
|
||||
|
||||
const NzCamera* NzScene::GetActiveCamera() const
|
||||
NzCamera* NzScene::GetActiveCamera() const
|
||||
{
|
||||
return m_impl->activeCamera;
|
||||
}
|
||||
|
||||
NzColor NzScene::GetAmbientColor() const
|
||||
{
|
||||
return m_impl->ambientColor;
|
||||
}
|
||||
|
||||
NzBackground* NzScene::GetBackground() const
|
||||
{
|
||||
return m_impl->background.get();
|
||||
}
|
||||
|
||||
NzAbstractRenderTechnique* NzScene::GetRenderTechnique() const
|
||||
{
|
||||
return m_impl->renderTechnique.get();
|
||||
}
|
||||
|
||||
NzSceneNode& NzScene::GetRoot() const
|
||||
{
|
||||
return m_impl->root;
|
||||
@@ -371,6 +139,11 @@ void NzScene::SetBackground(NzBackground* background)
|
||||
m_impl->background.reset(background);
|
||||
}
|
||||
|
||||
void NzScene::SetRenderTechnique(NzAbstractRenderTechnique* renderTechnique)
|
||||
{
|
||||
m_impl->renderTechnique.reset(renderTechnique);
|
||||
}
|
||||
|
||||
void NzScene::SetUpdatePerSecond(unsigned int updatePerSecond)
|
||||
{
|
||||
m_impl->updatePerSecond = updatePerSecond;
|
||||
@@ -419,7 +192,7 @@ NzScene::operator const NzSceneNode&() const
|
||||
return m_impl->root;
|
||||
}
|
||||
|
||||
void NzScene::RecursiveFrustumCull(NzRenderQueue& renderQueue, const NzFrustumf& frustum, NzNode* node)
|
||||
void NzScene::RecursiveFrustumCull(NzAbstractRenderQueue* renderQueue, const NzFrustumf& frustum, NzNode* node)
|
||||
{
|
||||
for (NzNode* child : node->GetChilds())
|
||||
{
|
||||
@@ -437,7 +210,7 @@ void NzScene::RecursiveFrustumCull(NzRenderQueue& renderQueue, const NzFrustumf&
|
||||
}
|
||||
}
|
||||
|
||||
void NzScene::SetActiveCamera(const NzCamera* camera)
|
||||
void NzScene::SetActiveCamera(NzCamera* camera)
|
||||
{
|
||||
m_impl->activeCamera = camera;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ NzSceneRoot::NzSceneRoot(NzScene* scene)
|
||||
|
||||
NzSceneRoot::~NzSceneRoot() = default;
|
||||
|
||||
void NzSceneRoot::AddToRenderQueue(NzRenderQueue& renderQueue) const
|
||||
void NzSceneRoot::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const
|
||||
{
|
||||
NazaraUnused(renderQueue);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user