Added RenderTarget listeners

Moved Camera matrices assignation to RenderTechnique


Former-commit-id: c8a4ff4b35d40702f047fdfd3fdbc4e4fbbbb1a9
This commit is contained in:
Lynix 2013-08-09 18:25:30 +02:00
parent bee3652604
commit d509fddc82
8 changed files with 242 additions and 53 deletions

View File

@ -13,10 +13,9 @@
#include <Nazara/Math/Matrix4.hpp> #include <Nazara/Math/Matrix4.hpp>
#include <Nazara/Math/Rect.hpp> #include <Nazara/Math/Rect.hpp>
#include <Nazara/Math/Vector3.hpp> #include <Nazara/Math/Vector3.hpp>
#include <Nazara/Renderer/RenderTarget.hpp>
class NzRenderTarget; class NAZARA_API NzCamera : public NzSceneNode, NzRenderTarget::Listener
class NAZARA_API NzCamera : public NzSceneNode
{ {
public: public:
NzCamera(); NzCamera();
@ -35,36 +34,47 @@ class NAZARA_API NzCamera : public NzSceneNode
const NzMatrix4f& GetProjectionMatrix() const; const NzMatrix4f& GetProjectionMatrix() const;
nzSceneNodeType GetSceneNodeType() const override; nzSceneNodeType GetSceneNodeType() const override;
const NzRenderTarget* GetTarget() const; const NzRenderTarget* GetTarget() const;
const NzRectf& GetTargetRegion() const;
const NzMatrix4f& GetViewMatrix() const; const NzMatrix4f& GetViewMatrix() const;
const NzRectf& GetViewport() const; const NzRectui& GetViewport() const;
float GetZFar() const; float GetZFar() const;
float GetZNear() const; float GetZNear() const;
void SetFOV(float fov); void SetFOV(float fov);
void SetTarget(const NzRenderTarget* renderTarget); void SetTarget(const NzRenderTarget* renderTarget);
void SetTarget(const NzRenderTarget& renderTarget); void SetTarget(const NzRenderTarget& renderTarget);
void SetViewport(const NzRectf& viewport); void SetTargetRegion(const NzRectf& region);
void SetViewport(const NzRectui& viewport);
void SetZFar(float zFar); void SetZFar(float zFar);
void SetZNear(float zNear); void SetZNear(float zNear);
private: private:
void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const override; void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const override;
void Invalidate(); void Invalidate();
void Register();
void Unregister(); void OnRenderTargetReleased(const NzRenderTarget* renderTarget, void* userdata) override;
bool OnRenderTargetSizeChange(const NzRenderTarget* renderTarget, void* userdata) override;
void Register() override;
void Unregister() override;
void UpdateFrustum() const; void UpdateFrustum() const;
void UpdateProjectionMatrix() const; void UpdateProjectionMatrix() const;
void UpdateViewMatrix() const; void UpdateViewMatrix() const;
void UpdateViewport() const;
bool VisibilityTest(const NzFrustumf& frustum) override; bool VisibilityTest(const NzFrustumf& frustum) override;
mutable NzFrustumf m_frustum; mutable NzFrustumf m_frustum;
mutable NzMatrix4f m_projectionMatrix; mutable NzMatrix4f m_projectionMatrix;
mutable NzMatrix4f m_viewMatrix; mutable NzMatrix4f m_viewMatrix;
NzRectf m_viewport; NzRectf m_targetRegion;
mutable NzRectui m_viewport;
const NzRenderTarget* m_target; const NzRenderTarget* m_target;
mutable bool m_frustumUpdated; mutable bool m_frustumUpdated;
mutable bool m_projectionMatrixUpdated; mutable bool m_projectionMatrixUpdated;
mutable bool m_viewMatrixUpdated; mutable bool m_viewMatrixUpdated;
mutable bool m_viewportUpdated;
mutable float m_aspectRatio; mutable float m_aspectRatio;
float m_fov; float m_fov;
float m_zFar; float m_zFar;

View File

@ -10,6 +10,7 @@
#include <Nazara/Prerequesites.hpp> #include <Nazara/Prerequesites.hpp>
#include <Nazara/Renderer/Config.hpp> #include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/RenderTargetParameters.hpp> #include <Nazara/Renderer/RenderTargetParameters.hpp>
#include <unordered_map>
class NzRenderer; class NzRenderer;
@ -18,9 +19,13 @@ class NAZARA_API NzRenderTarget
friend class NzRenderer; friend class NzRenderer;
public: public:
NzRenderTarget() = default; class Listener;
NzRenderTarget();
virtual ~NzRenderTarget(); virtual ~NzRenderTarget();
void AddListener(Listener* listener, void* userdata = nullptr) const;
virtual unsigned int GetHeight() const = 0; virtual unsigned int GetHeight() const = 0;
virtual NzRenderTargetParameters GetParameters() const = 0; virtual NzRenderTargetParameters GetParameters() const = 0;
virtual unsigned int GetWidth() const = 0; virtual unsigned int GetWidth() const = 0;
@ -28,14 +33,34 @@ class NAZARA_API NzRenderTarget
bool IsActive() const; bool IsActive() const;
virtual bool IsRenderable() const = 0; virtual bool IsRenderable() const = 0;
void RemoveListener(Listener* listener) const;
bool SetActive(bool active); bool SetActive(bool active);
// Fonctions OpenGL // Fonctions OpenGL
virtual bool HasContext() const = 0; virtual bool HasContext() const = 0;
class Listener
{
public:
Listener() = default;
~Listener();
virtual bool OnRenderTargetParametersChange(const NzRenderTarget* renderTarget, void* userdata);
virtual void OnRenderTargetReleased(const NzRenderTarget* renderTarget, void* userdata);
virtual bool OnRenderTargetSizeChange(const NzRenderTarget* renderTarget, void* userdata);
};
protected: protected:
virtual bool Activate() const = 0; virtual bool Activate() const = 0;
virtual void Desactivate() const; virtual void Desactivate() const;
void NotifyParametersChange();
void NotifySizeChange();
private:
mutable std::unordered_map<Listener*, void*> m_listeners;
bool m_listenersLocked;
}; };
#endif // NAZARA_RENDERTARGET_HPP #endif // NAZARA_RENDERTARGET_HPP

View File

@ -10,9 +10,11 @@
NzCamera::NzCamera() : NzCamera::NzCamera() :
m_viewport(0.f, 0.f, 1.f, 1.f), m_viewport(0.f, 0.f, 1.f, 1.f),
m_target(nullptr),
m_frustumUpdated(false), m_frustumUpdated(false),
m_projectionMatrixUpdated(false), m_projectionMatrixUpdated(false),
m_viewMatrixUpdated(false), m_viewMatrixUpdated(false),
m_viewportUpdated(false),
m_aspectRatio(0.f), m_aspectRatio(0.f),
m_fov(70.f), m_fov(70.f),
m_zFar(100.f), m_zFar(100.f),
@ -20,50 +22,27 @@ m_zNear(1.f)
{ {
} }
NzCamera::~NzCamera() = default; NzCamera::~NzCamera()
{
if (m_target)
m_target->RemoveListener(this);
}
void NzCamera::Activate() void NzCamera::Activate()
{ {
#ifdef NAZARA_GRAPHICS_SAFE #ifdef NAZARA_GRAPHICS_SAFE
if (!m_target) if (!m_target)
{ {
NazaraError("No render target !"); NazaraError("Camera has no render target");
return; return;
} }
#endif #endif
if (!m_viewportUpdated)
UpdateViewport();
NzRenderer::SetTarget(m_target); NzRenderer::SetTarget(m_target);
NzRenderer::SetViewport(m_viewport);
unsigned int width = m_target->GetWidth();
unsigned int height = std::max(m_target->GetHeight(), 1U);
float vWidth = width * m_viewport.width;
float vHeight = height * m_viewport.height;
NzRectui viewport;
viewport.x = width * m_viewport.x;
viewport.y = height * m_viewport.x;
viewport.width = vWidth;
viewport.height = height * m_viewport.height;
NzRenderer::SetViewport(viewport);
float aspectRatio = vWidth/vHeight;
if (!NzNumberEquals(m_aspectRatio, aspectRatio))
{
m_aspectRatio = aspectRatio;
m_frustumUpdated = false;
m_projectionMatrixUpdated = false;
}
if (!m_projectionMatrixUpdated)
UpdateProjectionMatrix();
if (!m_viewMatrixUpdated)
UpdateViewMatrix();
NzRenderer::SetMatrix(nzMatrixType_Projection, m_projectionMatrix);
NzRenderer::SetMatrix(nzMatrixType_View, m_viewMatrix);
if (m_scene) if (m_scene)
m_scene->SetActiveCamera(this); m_scene->SetActiveCamera(this);
@ -130,6 +109,11 @@ const NzRenderTarget* NzCamera::GetTarget() const
return m_target; return m_target;
} }
const NzRectf& NzCamera::GetTargetRegion() const
{
return m_targetRegion;
}
const NzMatrix4f& NzCamera::GetViewMatrix() const const NzMatrix4f& NzCamera::GetViewMatrix() const
{ {
if (!m_viewMatrixUpdated) if (!m_viewMatrixUpdated)
@ -138,8 +122,19 @@ const NzMatrix4f& NzCamera::GetViewMatrix() const
return m_viewMatrix; return m_viewMatrix;
} }
const NzRectf& NzCamera::GetViewport() const const NzRectui& NzCamera::GetViewport() const
{ {
#if NAZARA_GRAPHICS_SAFE
if (!m_target)
{
NazaraError("Camera has no render target");
return m_viewport;
}
#endif
if (!m_viewportUpdated)
UpdateViewport();
return m_viewport; return m_viewport;
} }
@ -163,7 +158,13 @@ void NzCamera::SetFOV(float fov)
void NzCamera::SetTarget(const NzRenderTarget* renderTarget) void NzCamera::SetTarget(const NzRenderTarget* renderTarget)
{ {
NazaraError(NzString::Pointer(m_target));
if (m_target)
m_target->RemoveListener(this);
m_target = renderTarget; m_target = renderTarget;
if (m_target)
m_target->AddListener(this);
} }
void NzCamera::SetTarget(const NzRenderTarget& renderTarget) void NzCamera::SetTarget(const NzRenderTarget& renderTarget)
@ -171,9 +172,27 @@ void NzCamera::SetTarget(const NzRenderTarget& renderTarget)
SetTarget(&renderTarget); SetTarget(&renderTarget);
} }
void NzCamera::SetViewport(const NzRectf& viewport) void NzCamera::SetTargetRegion(const NzRectf& region)
{ {
m_viewport = viewport; m_targetRegion = region;
m_viewportUpdated = false;
}
void NzCamera::SetViewport(const NzRectui& viewport)
{
#if NAZARA_GRAPHICS_SAFE
if (!m_target)
{
NazaraError("Camera has no render target");
return;
}
#endif
// On calcule la région nécessaire pour produire ce viewport avec la taille actuelle de la cible
float invWidth = 1.f/m_target->GetWidth();
float invHeight = 1.f/m_target->GetHeight();
SetTargetRegion(NzRectf(invWidth * viewport.x, invHeight * viewport.y, invWidth * viewport.width, invHeight * viewport.height));
} }
void NzCamera::SetZFar(float zFar) void NzCamera::SetZFar(float zFar)
@ -196,17 +215,40 @@ void NzCamera::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const
{ {
NazaraUnused(renderQueue); NazaraUnused(renderQueue);
NazaraInternalError("SceneNode::AddToRenderQueue() called on SceneRoot"); NazaraInternalError("SceneNode::AddToRenderQueue() called on Camera");
} }
void NzCamera::Invalidate() void NzCamera::Invalidate()
{ {
NzSceneNode::Invalidate(); NzSceneNode::Invalidate();
// Le frustum et la view matrix dépendent des paramètres du node, invalidons-les
m_frustumUpdated = false; m_frustumUpdated = false;
m_viewMatrixUpdated = false; m_viewMatrixUpdated = false;
} }
void NzCamera::OnRenderTargetReleased(const NzRenderTarget* renderTarget, void* userdata)
{
NazaraUnused(userdata);
if (renderTarget == m_target)
m_target = nullptr;
else
NazaraInternalError("Not listening to " + NzString::Pointer(renderTarget));
}
bool NzCamera::OnRenderTargetSizeChange(const NzRenderTarget* renderTarget, void* userdata)
{
NazaraUnused(userdata);
if (renderTarget == m_target)
m_viewportUpdated = false;
else
NazaraInternalError("Not listening to " + NzString::Pointer(renderTarget));
return true;
}
void NzCamera::Register() void NzCamera::Register()
{ {
} }
@ -242,6 +284,29 @@ void NzCamera::UpdateViewMatrix() const
m_viewMatrixUpdated = true; m_viewMatrixUpdated = true;
} }
void NzCamera::UpdateViewport() const
{
unsigned int width = m_target->GetWidth();
unsigned int height = std::max(m_target->GetHeight(), 1U);
float vWidth = width * m_viewport.width;
float vHeight = height * m_viewport.height;
float aspectRatio = vWidth/vHeight;
if (!NzNumberEquals(m_aspectRatio, aspectRatio, 0.001f))
{
m_aspectRatio = aspectRatio;
m_frustumUpdated = false;
m_projectionMatrixUpdated = false;
}
m_viewport.x = width * m_targetRegion.x;
m_viewport.y = height * m_targetRegion.y;
m_viewport.width = vWidth;
m_viewport.height = vHeight;
m_viewportUpdated = true;
}
bool NzCamera::VisibilityTest(const NzFrustumf& frustum) bool NzCamera::VisibilityTest(const NzFrustumf& frustum)
{ {
NazaraUnused(frustum); NazaraUnused(frustum);

View File

@ -140,6 +140,9 @@ void NzForwardRenderTechnique::Draw(const NzScene* scene)
const NzCamera* camera = scene->GetActiveCamera(); const NzCamera* camera = scene->GetActiveCamera();
const NzShaderProgram* lastProgram = nullptr; const NzShaderProgram* lastProgram = nullptr;
NzRenderer::SetMatrix(nzMatrixType_Projection, camera->GetProjectionMatrix());
NzRenderer::SetMatrix(nzMatrixType_View, camera->GetViewMatrix());
// Rendu des modèles opaques // Rendu des modèles opaques
for (auto& matIt : m_renderQueue.opaqueModels) for (auto& matIt : m_renderQueue.opaqueModels)
{ {

View File

@ -198,13 +198,14 @@ void NzSkyboxBackground::Draw(const NzScene* scene) const
s_program->SendInteger(s_skyboxLocation, 0); s_program->SendInteger(s_skyboxLocation, 0);
const NzMatrix4f& viewMatrix = NzRenderer::GetMatrix(nzMatrixType_View); NzCamera* camera = scene->GetActiveCamera();
NzMatrix4f skyboxMatrix(viewMatrix);
NzMatrix4f skyboxMatrix(camera->GetViewMatrix());
skyboxMatrix.SetTranslation(NzVector3f::Zero()); skyboxMatrix.SetTranslation(NzVector3f::Zero());
NzRenderer::SetIndexBuffer(m_indexBuffer); NzRenderer::SetIndexBuffer(m_indexBuffer);
NzRenderer::SetMatrix(nzMatrixType_View, skyboxMatrix); NzRenderer::SetMatrix(nzMatrixType_View, skyboxMatrix);
NzRenderer::SetMatrix(nzMatrixType_World, NzMatrix4f::Scale(NzVector3f(scene->GetActiveCamera()->GetZNear()))); NzRenderer::SetMatrix(nzMatrixType_World, NzMatrix4f::Scale(NzVector3f(camera->GetZNear())));
NzRenderer::SetRenderStates(states); NzRenderer::SetRenderStates(states);
NzRenderer::SetShaderProgram(s_program); NzRenderer::SetShaderProgram(s_program);
NzRenderer::SetTexture(0, m_texture); NzRenderer::SetTexture(0, m_texture);
@ -212,8 +213,6 @@ void NzSkyboxBackground::Draw(const NzScene* scene) const
NzRenderer::SetVertexBuffer(m_vertexBuffer); NzRenderer::SetVertexBuffer(m_vertexBuffer);
NzRenderer::DrawIndexedPrimitives(nzPrimitiveMode_TriangleList, 0, 36); NzRenderer::DrawIndexedPrimitives(nzPrimitiveMode_TriangleList, 0, 36);
NzRenderer::SetMatrix(nzMatrixType_View, viewMatrix);
} }
nzBackgroundType NzSkyboxBackground::GetBackgroundType() const nzBackgroundType NzSkyboxBackground::GetBackgroundType() const

View File

@ -6,13 +6,37 @@
#include <Nazara/Renderer/Renderer.hpp> #include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Renderer/Debug.hpp> #include <Nazara/Renderer/Debug.hpp>
NzRenderTarget::~NzRenderTarget() = default; NzRenderTarget::NzRenderTarget() :
m_listenersLocked(false)
{
}
NzRenderTarget::~NzRenderTarget()
{
m_listenersLocked = true;
for (auto& pair : m_listeners)
pair.first->OnRenderTargetReleased(this, pair.second);
}
void NzRenderTarget::AddListener(Listener* listener, void* userdata) const
{
NazaraError("What the");
if (!m_listenersLocked)
m_listeners.insert(std::make_pair(listener, userdata));
NazaraError("What the");
}
bool NzRenderTarget::IsActive() const bool NzRenderTarget::IsActive() const
{ {
return NzRenderer::GetTarget() == this; return NzRenderer::GetTarget() == this;
} }
void NzRenderTarget::RemoveListener(Listener* listener) const
{
if (!m_listenersLocked)
m_listeners.erase(listener);
}
bool NzRenderTarget::SetActive(bool active) bool NzRenderTarget::SetActive(bool active)
{ {
if (active) if (active)
@ -27,3 +51,59 @@ void NzRenderTarget::Desactivate() const
{ {
// Seuls les target sans contextes (ex: NzRenderTexture) nécessitent une désactivation // Seuls les target sans contextes (ex: NzRenderTexture) nécessitent une désactivation
} }
void NzRenderTarget::NotifyParametersChange()
{
m_listenersLocked = true;
auto it = m_listeners.begin();
while (it != m_listeners.end())
{
if (!it->first->OnRenderTargetParametersChange(this, it->second))
m_listeners.erase(it++);
else
++it;
}
m_listenersLocked = false;
}
void NzRenderTarget::NotifySizeChange()
{
m_listenersLocked = true;
auto it = m_listeners.begin();
while (it != m_listeners.end())
{
if (!it->first->OnRenderTargetSizeChange(this, it->second))
m_listeners.erase(it++);
else
++it;
}
m_listenersLocked = false;
}
NzRenderTarget::Listener::~Listener() = default;
bool NzRenderTarget::Listener::OnRenderTargetParametersChange(const NzRenderTarget* renderTarget, void* userdata)
{
NazaraUnused(renderTarget);
NazaraUnused(userdata);
return true;
}
void NzRenderTarget::Listener::OnRenderTargetReleased(const NzRenderTarget* renderTarget, void* userdata)
{
NazaraUnused(renderTarget);
NazaraUnused(userdata);
}
bool NzRenderTarget::Listener::OnRenderTargetSizeChange(const NzRenderTarget* renderTarget, void* userdata)
{
NazaraUnused(renderTarget);
NazaraUnused(userdata);
return true;
}

View File

@ -317,6 +317,9 @@ bool NzRenderTexture::Create(unsigned int width, unsigned int height, bool lock)
return false; return false;
} }
NotifyParametersChange();
NotifySizeChange();
return true; return true;
} }
@ -435,6 +438,7 @@ NzRenderTargetParameters NzRenderTexture::GetParameters() const
} }
#endif #endif
///TODO
return NzRenderTargetParameters(); return NzRenderTargetParameters();
} }

View File

@ -294,6 +294,9 @@ bool NzRenderWindow::OnWindowCreated()
if (!SetActive(true)) // Les fenêtres s'activent à la création if (!SetActive(true)) // Les fenêtres s'activent à la création
NazaraWarning("Failed to activate window"); NazaraWarning("Failed to activate window");
NotifyParametersChange();
NotifySizeChange();
m_clock.Restart(); m_clock.Restart();
return true; return true;