diff --git a/include/Nazara/Graphics.hpp b/include/Nazara/Graphics.hpp index 87e179731..411200e53 100644 --- a/include/Nazara/Graphics.hpp +++ b/include/Nazara/Graphics.hpp @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include diff --git a/include/Nazara/Graphics/AbstractRenderQueue.hpp b/include/Nazara/Graphics/AbstractRenderQueue.hpp new file mode 100644 index 000000000..2246e94b2 --- /dev/null +++ b/include/Nazara/Graphics/AbstractRenderQueue.hpp @@ -0,0 +1,30 @@ +// 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 + +#pragma once + +#ifndef NAZARA_ABSTRACTRENDERQUEUE_HPP +#define NAZARA_ABSTRACTRENDERQUEUE_HPP + +#include +#include + +class NzDrawable; +class NzLight; +class NzModel; + +class NAZARA_API NzAbstractRenderQueue : NzNonCopyable +{ + public: + NzAbstractRenderQueue() = default; + virtual ~NzAbstractRenderQueue(); + + virtual void AddDrawable(const NzDrawable* drawable) = 0; + virtual void AddLight(const NzLight* light) = 0; + virtual void AddModel(const NzModel* model) = 0; + + virtual void Clear() = 0; +}; + +#endif // NAZARA_ABSTRACTRENDERQUEUE_HPP diff --git a/include/Nazara/Graphics/AbstractRenderTechnique.hpp b/include/Nazara/Graphics/AbstractRenderTechnique.hpp new file mode 100644 index 000000000..b390597e3 --- /dev/null +++ b/include/Nazara/Graphics/AbstractRenderTechnique.hpp @@ -0,0 +1,29 @@ +// 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 + +#pragma once + +#ifndef NAZARA_ABSTRACTRENDERTECHNIQUE_HPP +#define NAZARA_ABSTRACTRENDERTECHNIQUE_HPP + +#include +#include +#include + +class NzBackground; +class NzScene; + +class NAZARA_API NzAbstractRenderTechnique : NzNonCopyable +{ + public: + NzAbstractRenderTechnique() = default; + virtual ~NzAbstractRenderTechnique(); + + virtual void Clear(const NzScene* scene) = 0; + virtual void Draw(const NzScene* scene) = 0; + + virtual NzAbstractRenderQueue* GetRenderQueue() = 0; +}; + +#endif // NAZARA_ABSTRACTRENDERTECHNIQUE_HPP diff --git a/include/Nazara/Graphics/Camera.hpp b/include/Nazara/Graphics/Camera.hpp index 2e536ef3f..724cd4c75 100644 --- a/include/Nazara/Graphics/Camera.hpp +++ b/include/Nazara/Graphics/Camera.hpp @@ -22,7 +22,7 @@ class NAZARA_API NzCamera : public NzSceneNode NzCamera(); ~NzCamera(); - void Activate() const; + void Activate(); void EnsureFrustumUpdate() const; void EnsureProjectionMatrixUpdate() const; @@ -50,7 +50,7 @@ class NAZARA_API NzCamera : public NzSceneNode void SetZNear(float zNear); private: - void AddToRenderQueue(NzRenderQueue& renderQueue) const; + void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const override; void Invalidate(); void Register(); void Unregister(); diff --git a/include/Nazara/Graphics/RenderQueue.hpp b/include/Nazara/Graphics/ForwardRenderQueue.hpp similarity index 60% rename from include/Nazara/Graphics/RenderQueue.hpp rename to include/Nazara/Graphics/ForwardRenderQueue.hpp index a5d2f3a7e..4c83d4245 100644 --- a/include/Nazara/Graphics/RenderQueue.hpp +++ b/include/Nazara/Graphics/ForwardRenderQueue.hpp @@ -2,60 +2,49 @@ // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp -#ifndef NAZARA_RENDERQUEUE_HPP -#define NAZARA_RENDERQUEUE_HPP +#pragma once + +#ifndef NAZARA_FORWARDRENDERQUEUE_HPP +#define NAZARA_FORWARDRENDERQUEUE_HPP #include +#include #include -#include #include -#include -class NzDrawable; -class NzLight; +class NzCamera; class NzMaterial; -class NzModel; class NzSkeletalMesh; class NzStaticMesh; -class NAZARA_API NzRenderQueue +class NAZARA_API NzForwardRenderQueue : public NzAbstractRenderQueue { + friend class NzForwardRenderTechnique; + public: - NzRenderQueue() = default; - ~NzRenderQueue() = default; + NzForwardRenderQueue() = default; + ~NzForwardRenderQueue() = default; + + void AddDrawable(const NzDrawable* drawable); + void AddLight(const NzLight* light); + void AddModel(const NzModel* model); void Clear(); - struct SkeletalData - { - NzMatrix4f transformMatrix; - - ///TODO: Déplacer vers un container séparé qui ne serait pas sujet à Clear(); - std::vector skinnedVertices; - }; - - struct TransparentModel - { - NzMatrix4f transformMatrix; - NzMaterial* material; - }; - - struct TransparentSkeletalModel : public TransparentModel - { - ///TODO: Déplacer vers un container séparé qui ne serait pas sujet à Clear(); - std::vector skinnedVertices; - }; - - struct TransparentStaticModel : public TransparentModel - { - NzStaticMesh* mesh; - }; + void Sort(const NzCamera& camera); + private: struct MaterialComparator { bool operator()(const NzMaterial* mat1, const NzMaterial* mat2); }; + struct SkeletalData + { + ///TODO + NzMatrix4f transformMatrix; + }; + struct SkeletalMeshComparator { bool operator()(const NzSkeletalMesh* subMesh1, const NzSkeletalMesh* subMesh2); @@ -66,16 +55,32 @@ class NAZARA_API NzRenderQueue bool operator()(const NzStaticMesh* subMesh1, const NzStaticMesh* subMesh2); }; + struct TransparentModel + { + NzMatrix4f transformMatrix; + NzMaterial* material; + }; + + struct TransparentSkeletalModel : public TransparentModel + { + ///TODO + }; + + struct TransparentStaticModel : public TransparentModel + { + NzStaticMesh* mesh; + }; + typedef std::map, SkeletalMeshComparator> SkeletalMeshContainer; typedef std::map, StaticMeshComparator> StaticMeshContainer; - std::map visibleSkeletalModels; - std::map visibleStaticModels; - std::vector visibleTransparentSkeletalModels; - std::vector visibleTransparentStaticModels; + std::map, MaterialComparator> visibleModels; + std::vector> visibleTransparentsModels; + std::vector transparentSkeletalModels; + std::vector transparentStaticModels; std::vector otherDrawables; std::vector directionnalLights; std::vector visibleLights; }; -#endif // NAZARA_RENDERQUEUE_HPP +#endif // NAZARA_FORWARDRENDERQUEUE_HPP diff --git a/include/Nazara/Graphics/ForwardRenderTechnique.hpp b/include/Nazara/Graphics/ForwardRenderTechnique.hpp new file mode 100644 index 000000000..385b5f7e2 --- /dev/null +++ b/include/Nazara/Graphics/ForwardRenderTechnique.hpp @@ -0,0 +1,33 @@ +// 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 + +#pragma once + +#ifndef NAZARA_FORWARDRENDERTECHNIQUE_HPP +#define NAZARA_FORWARDRENDERTECHNIQUE_HPP + +#include +#include +#include + +class NAZARA_API NzForwardRenderTechnique : public NzAbstractRenderTechnique +{ + public: + NzForwardRenderTechnique(); + ~NzForwardRenderTechnique() = default; + + void Clear(const NzScene* scene); + void Draw(const NzScene* scene); + + unsigned int GetMaxLightsPerObject() const; + NzAbstractRenderQueue* GetRenderQueue() override; + + void SetMaxLightsPerObject(unsigned int lightCount); + + private: + NzForwardRenderQueue m_renderQueue; + unsigned int m_maxLightsPerObject; +}; + +#endif // NAZARA_FORWARDRENDERTECHNIQUE_HPP diff --git a/include/Nazara/Graphics/Light.hpp b/include/Nazara/Graphics/Light.hpp index 048a5d210..6492a1081 100644 --- a/include/Nazara/Graphics/Light.hpp +++ b/include/Nazara/Graphics/Light.hpp @@ -19,9 +19,9 @@ class NAZARA_API NzLight : public NzSceneNode public: NzLight(nzLightType type); NzLight(const NzLight& light); - ~NzLight(); + ~NzLight() = default; - void AddToRenderQueue(NzRenderQueue& renderQueue) const; + void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const override; void Apply(const NzShader* shader, unsigned int lightUnit) const; diff --git a/include/Nazara/Graphics/Model.hpp b/include/Nazara/Graphics/Model.hpp index bff162ee0..603d7dbda 100644 --- a/include/Nazara/Graphics/Model.hpp +++ b/include/Nazara/Graphics/Model.hpp @@ -41,7 +41,7 @@ class NAZARA_API NzModel : public NzSceneNode, public NzUpdatable NzModel(NzModel&& model); ~NzModel(); - void AddToRenderQueue(NzRenderQueue& renderQueue) const; + void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const override; void AdvanceAnimation(float elapsedTime); void EnableAnimation(bool animation); @@ -64,6 +64,7 @@ class NAZARA_API NzModel : public NzSceneNode, public NzUpdatable bool HasAnimation() const; bool IsAnimationEnabled() const; + bool IsDrawable() const; bool IsDrawEnabled() const; bool LoadFromFile(const NzString& filePath, const NzModelParameters& params = NzModelParameters()); diff --git a/include/Nazara/Graphics/Scene.hpp b/include/Nazara/Graphics/Scene.hpp index beaa10cd7..ab394d92e 100644 --- a/include/Nazara/Graphics/Scene.hpp +++ b/include/Nazara/Graphics/Scene.hpp @@ -10,9 +10,11 @@ #include #include #include +#include #include #include +class NzAbstractRenderQueue; class NzCamera; class NzLight; class NzModel; @@ -34,8 +36,10 @@ class NAZARA_API NzScene void Cull(); void Draw(); - const NzCamera* GetActiveCamera() const; + NzCamera* GetActiveCamera() const; + NzColor GetAmbientColor() const; NzBackground* GetBackground() const; + NzAbstractRenderTechnique* GetRenderTechnique() const; NzSceneNode& GetRoot() const; float GetUpdateTime() const; unsigned int GetUpdatePerSecond() const; @@ -44,6 +48,7 @@ class NAZARA_API NzScene void SetAmbientColor(const NzColor& color); void SetBackground(NzBackground* background); + void SetRenderTechnique(NzAbstractRenderTechnique* renderTechnique); void SetUpdatePerSecond(unsigned int updatePerSecond); void UnregisterForUpdate(NzUpdatable* object); @@ -54,8 +59,8 @@ class NAZARA_API NzScene operator const NzSceneNode&() const; private: - void RecursiveFrustumCull(NzRenderQueue& renderQueue, const NzFrustumf& frustum, NzNode* node); - void SetActiveCamera(const NzCamera* camera); + void RecursiveFrustumCull(NzAbstractRenderQueue* renderQueue, const NzFrustumf& frustum, NzNode* node); + void SetActiveCamera(NzCamera* camera); NzSceneImpl* m_impl; }; diff --git a/include/Nazara/Graphics/SceneNode.hpp b/include/Nazara/Graphics/SceneNode.hpp index ba2b010a3..871939eb8 100644 --- a/include/Nazara/Graphics/SceneNode.hpp +++ b/include/Nazara/Graphics/SceneNode.hpp @@ -9,7 +9,6 @@ #include #include -#include #include #include #include @@ -24,7 +23,7 @@ class NAZARA_API NzSceneNode : public NzNode NzSceneNode(const NzSceneNode& node); virtual ~NzSceneNode(); - virtual void AddToRenderQueue(NzRenderQueue& renderQueue) const = 0; + virtual void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const = 0; virtual const NzBoundingBoxf& GetBoundingBox() const = 0; nzNodeType GetNodeType() const final; diff --git a/include/Nazara/Graphics/SceneRoot.hpp b/include/Nazara/Graphics/SceneRoot.hpp index c28651b70..a84b0f970 100644 --- a/include/Nazara/Graphics/SceneRoot.hpp +++ b/include/Nazara/Graphics/SceneRoot.hpp @@ -17,7 +17,7 @@ class NAZARA_API NzSceneRoot : public NzSceneNode friend struct NzSceneImpl; public: - void AddToRenderQueue(NzRenderQueue& renderQueue) const override; + void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const override; const NzBoundingBoxf& GetBoundingBox() const override; nzSceneNodeType GetSceneNodeType() const override; diff --git a/src/Nazara/Graphics/AbstractRenderQueue.cpp b/src/Nazara/Graphics/AbstractRenderQueue.cpp new file mode 100644 index 000000000..d4cf28f7a --- /dev/null +++ b/src/Nazara/Graphics/AbstractRenderQueue.cpp @@ -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 +#include + +NzAbstractRenderQueue::~NzAbstractRenderQueue() = default; diff --git a/src/Nazara/Graphics/AbstractRenderTechnique.cpp b/src/Nazara/Graphics/AbstractRenderTechnique.cpp new file mode 100644 index 000000000..c41001b7b --- /dev/null +++ b/src/Nazara/Graphics/AbstractRenderTechnique.cpp @@ -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 +#include + +NzAbstractRenderTechnique::~NzAbstractRenderTechnique() = default; diff --git a/src/Nazara/Graphics/Camera.cpp b/src/Nazara/Graphics/Camera.cpp index 96234b7f6..3a9b8ffa3 100644 --- a/src/Nazara/Graphics/Camera.cpp +++ b/src/Nazara/Graphics/Camera.cpp @@ -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); diff --git a/src/Nazara/Graphics/ForwardRenderQueue.cpp b/src/Nazara/Graphics/ForwardRenderQueue.cpp new file mode 100644 index 000000000..f892bfc98 --- /dev/null +++ b/src/Nazara/Graphics/ForwardRenderQueue.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include + +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(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& index1, const std::pair& 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; +} diff --git a/src/Nazara/Graphics/ForwardRenderTechnique.cpp b/src/Nazara/Graphics/ForwardRenderTechnique.cpp new file mode 100644 index 000000000..21fc0350b --- /dev/null +++ b/src/Nazara/Graphics/ForwardRenderTechnique.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 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& 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(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& 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 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& 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(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; +} diff --git a/src/Nazara/Graphics/Light.cpp b/src/Nazara/Graphics/Light.cpp index 3fdb7ed87..cadcdc325 100644 --- a/src/Nazara/Graphics/Light.cpp +++ b/src/Nazara/Graphics/Light.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -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 diff --git a/src/Nazara/Graphics/Model.cpp b/src/Nazara/Graphics/Model.cpp index 10ba81fec..c89209bff 100644 --- a/src/Nazara/Graphics/Model.cpp +++ b/src/Nazara/Graphics/Model.cpp @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include #include #include @@ -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(subMesh); - std::vector& 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(subMesh); - std::vector& 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 diff --git a/src/Nazara/Graphics/RenderQueue.cpp b/src/Nazara/Graphics/RenderQueue.cpp deleted file mode 100644 index 59a6c5921..000000000 --- a/src/Nazara/Graphics/RenderQueue.cpp +++ /dev/null @@ -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 -#include -#include -#include -#include - -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(); -} diff --git a/src/Nazara/Graphics/Scene.cpp b/src/Nazara/Graphics/Scene.cpp index 8645e487f..c18326d0e 100644 --- a/src/Nazara/Graphics/Scene.cpp +++ b/src/Nazara/Graphics/Scene.cpp @@ -5,41 +5,17 @@ #include #include #include -#include -#include #include -#include -#include -#include +#include +#include #include #include -#include -#include -#include -#include -#include -#include #include #include #include #include #include -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 renderTechnique; std::unique_ptr background; std::vector updateList; std::vector visibleUpdateList; - std::vector 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(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 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 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(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 draw; - std::function 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& 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(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; } diff --git a/src/Nazara/Graphics/SceneRoot.cpp b/src/Nazara/Graphics/SceneRoot.cpp index 44cbb15c6..ed0670216 100644 --- a/src/Nazara/Graphics/SceneRoot.cpp +++ b/src/Nazara/Graphics/SceneRoot.cpp @@ -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);