diff --git a/examples/DeferredShading/main.cpp b/examples/DeferredShading/main.cpp index aa2b94f4d..a791715f5 100644 --- a/examples/DeferredShading/main.cpp +++ b/examples/DeferredShading/main.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -209,15 +210,11 @@ int main() Nz::PredefinedInstanceData instanceUboOffsets = Nz::PredefinedInstanceData::GetOffsets(); Nz::PredefinedViewerData viewerUboOffsets = Nz::PredefinedViewerData::GetOffsets(); - std::vector viewerDataBuffer(viewerUboOffsets.totalSize); - Nz::Vector2ui windowSize = window.GetSize(); - Nz::AccessByOffset(viewerDataBuffer.data(), viewerUboOffsets.viewMatrixOffset) = Nz::Matrix4f::Translate(Nz::Vector3f::Backward() * 1); - Nz::AccessByOffset(viewerDataBuffer.data(), viewerUboOffsets.projMatrixOffset) = Nz::Matrix4f::Perspective(Nz::DegreeAnglef(70.f), float(windowSize.x) / windowSize.y, 0.1f, 1000.f); - Nz::AccessByOffset(viewerDataBuffer.data(), viewerUboOffsets.invTargetSizeOffset) = 1.f / Nz::Vector2f(window.GetSize().x, window.GetSize().y); - - std::vector instanceDataBuffer(instanceUboOffsets.totalSize); + Nz::ViewerInstance viewerInstance; + viewerInstance.UpdateTargetSize(Nz::Vector2f(windowSize)); + viewerInstance.UpdateProjViewMatrices(Nz::Matrix4f::Perspective(Nz::DegreeAnglef(70.f), float(windowSize.x) / windowSize.y, 0.1f, 1000.f), Nz::Matrix4f::Translate(Nz::Vector3f::Backward() * 1)); Nz::ModelInstance modelInstance1(spaceshipMat->GetSettings()); spaceshipMat->UpdateShaderBinding(modelInstance1.GetShaderBinding()); @@ -520,7 +517,6 @@ int main() std::shared_ptr finalBlitBinding = fullscreenPipelineInfo.pipelineLayout->AllocateShaderBinding(); - bool viewerUboUpdate = true; bool lightUpdate = true; std::shared_ptr textureSampler = device->InstantiateTextureSampler({}); @@ -670,7 +666,7 @@ int main() Nz::FramePass& lightingPass = graph.AddPass("Lighting pass"); lightingPass.SetExecutionCallback([&] { - return (viewerUboUpdate) ? Nz::FramePassExecution::UpdateAndExecute : Nz::FramePassExecution::Execute; + return (lightUpdate) ? Nz::FramePassExecution::UpdateAndExecute : Nz::FramePassExecution::Execute; }); lightingPass.SetCommandCallback([&](Nz::CommandBufferBuilder& builder) @@ -1005,8 +1001,6 @@ int main() camAngles.pitch = Nz::Clamp(camAngles.pitch + event.mouseMove.deltaY*sensitivity, -89.f, 89.f); camQuat = camAngles; - - viewerUboUpdate = true; break; } @@ -1035,8 +1029,7 @@ int main() case Nz::WindowEventType::Resized: { Nz::Vector2ui windowSize = window.GetSize(); - Nz::AccessByOffset(viewerDataBuffer.data(), viewerUboOffsets.projMatrixOffset) = Nz::Matrix4f::Perspective(Nz::DegreeAnglef(70.f), float(windowSize.x) / windowSize.y, 0.1f, 1000.f); - viewerUboUpdate = true; + viewerInstance.UpdateProjViewMatrices(Nz::Matrix4f::Perspective(Nz::DegreeAnglef(70.f), float(windowSize.x) / windowSize.y, 0.1f, 1000.f), Nz::Matrix4f::Translate(Nz::Vector3f::Backward() * 1)); break; } @@ -1073,7 +1066,7 @@ int main() if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::LControl) || Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::RControl)) viewerPos += Nz::Vector3f::Down() * cameraSpeed; - viewerUboUpdate = true; + viewerInstance.UpdateViewMatrix(Nz::Matrix4f::ViewMatrix(viewerPos, camQuat)); } Nz::RenderFrame frame = windowImpl->Acquire(); @@ -1083,12 +1076,8 @@ int main() if (frame.IsFramebufferInvalidated()) RebuildCommandBuffer(); - if (viewerUboUpdate || lightAnimation || lightUpdate) + if (lightAnimation || lightUpdate) { - Nz::AccessByOffset(viewerDataBuffer.data(), viewerUboOffsets.viewMatrixOffset) = Nz::Matrix4f::ViewMatrix(viewerPos, camAngles); - - //Nz::AccessByOffset(lightData.data(), colorOffset) = Nz::Vector3f(std::sin(totalFrameCount / 10000.f) * 0.5f + 0.5f, std::cos(totalFrameCount / 1000.f) * 0.5f + 0.5f, std::sin(totalFrameCount / 100.f) * 0.5f + 0.5f); - Nz::UploadPool& uploadPool = frame.GetUploadPool(); frame.Execute([&](Nz::CommandBufferBuilder& builder) @@ -1097,12 +1086,11 @@ int main() { builder.PreTransferBarrier(); - if (viewerUboUpdate) - { - auto& viewerDataAllocation = uploadPool.Allocate(viewerDataBuffer.size()); - std::memcpy(viewerDataAllocation.mappedPtr, viewerDataBuffer.data(), viewerDataBuffer.size()); - builder.CopyBuffer(viewerDataAllocation, viewerDataUBO.get()); - } + modelInstance1.UpdateBuffers(uploadPool, builder); + modelInstance2.UpdateBuffers(uploadPool, builder); + planeInstance.UpdateBuffers(uploadPool, builder); + + viewerInstance.UpdateViewBuffer(uploadPool, builder); if (!spotLights.empty() && (lightUpdate || lightAnimation)) { @@ -1151,7 +1139,7 @@ int main() window.Display(); - viewerUboUpdate = false; + lightUpdate = false; // On incrémente le compteur de FPS improvisé fps++; diff --git a/include/Nazara/Graphics/ViewerInstance.hpp b/include/Nazara/Graphics/ViewerInstance.hpp new file mode 100644 index 000000000..4fa46d5fe --- /dev/null +++ b/include/Nazara/Graphics/ViewerInstance.hpp @@ -0,0 +1,57 @@ +// Copyright (C) 2017 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_VIEWERINSTANCE_HPP +#define NAZARA_VIEWERINSTANCE_HPP + +#include +#include +#include +#include +#include + +namespace Nz +{ + class AbstractBuffer; + class CommandBufferBuilder; + class MaterialSettings; + class UploadPool; + + class NAZARA_GRAPHICS_API ViewerInstance + { + public: + ViewerInstance(); + ViewerInstance(const ViewerInstance&) = delete; + ViewerInstance(ViewerInstance&&) noexcept = default; + ~ViewerInstance() = default; + + void UpdateViewBuffer(UploadPool& uploadPool, CommandBufferBuilder& builder); + inline void UpdateProjectionMatrix(const Matrix4f& projectionMatrix); + inline void UpdateProjectionMatrix(const Matrix4f& projectionMatrix, const Matrix4f& invProjectionMatrix); + inline void UpdateProjViewMatrices(const Matrix4f& projectionMatrix, const Matrix4f& viewMatrix); + inline void UpdateProjViewMatrices(const Matrix4f& projectionMatrix, const Matrix4f& invProjectionMatrix, const Matrix4f& viewMatrix, const Matrix4f& invViewMatrix); + inline void UpdateProjViewMatrices(const Matrix4f& projectionMatrix, const Matrix4f& invProjectionMatrix, const Matrix4f& viewMatrix, const Matrix4f& invViewMatrix, const Matrix4f& viewProjMatrix, const Matrix4f& invViewProjMatrix); + inline void UpdateTargetSize(const Vector2f& targetSize); + inline void UpdateViewMatrix(const Matrix4f& viewMatrix); + inline void UpdateViewMatrix(const Matrix4f& viewMatrix, const Matrix4f& invViewMatrix); + + ViewerInstance& operator=(const ViewerInstance&) = delete; + ViewerInstance& operator=(ViewerInstance&&) noexcept = default; + + private: + Matrix4f m_invProjectionMatrix; + Matrix4f m_invViewProjMatrix; + Matrix4f m_invViewMatrix; + Matrix4f m_projectionMatrix; + Matrix4f m_viewProjMatrix; + Matrix4f m_viewMatrix; + Vector2f m_targetSize; + }; +} + +#include + +#endif // NAZARA_VIEWERINSTANCE_HPP diff --git a/include/Nazara/Graphics/ViewerInstance.inl b/include/Nazara/Graphics/ViewerInstance.inl new file mode 100644 index 000000000..aa1f0c559 --- /dev/null +++ b/include/Nazara/Graphics/ViewerInstance.inl @@ -0,0 +1,82 @@ +// Copyright (C) 2017 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 + +namespace Nz +{ + inline void ViewerInstance::UpdateProjectionMatrix(const Matrix4f& projectionMatrix) + { + m_projectionMatrix = projectionMatrix; + if (!m_projectionMatrix.GetInverse(&m_invProjectionMatrix)) + NazaraError("failed to inverse projection matrix"); + } + + inline void ViewerInstance::UpdateProjectionMatrix(const Matrix4f& projectionMatrix, const Matrix4f& invProjectionMatrix) + { + m_projectionMatrix = projectionMatrix; + m_invProjectionMatrix = invProjectionMatrix; + } + + inline void ViewerInstance::UpdateProjViewMatrices(const Matrix4f& projectionMatrix, const Matrix4f& viewMatrix) + { + m_projectionMatrix = projectionMatrix; + if (!m_projectionMatrix.GetInverse(&m_invProjectionMatrix)) + NazaraError("failed to inverse projection matrix"); + + m_viewMatrix = viewMatrix; + if (!m_viewMatrix.GetInverseAffine(&m_invViewMatrix)) + NazaraError("failed to inverse view matrix"); + } + + inline void ViewerInstance::UpdateProjViewMatrices(const Matrix4f& projectionMatrix, const Matrix4f& invProjectionMatrix, const Matrix4f& viewMatrix, const Matrix4f& invViewMatrix) + { + m_projectionMatrix = projectionMatrix; + m_viewMatrix = viewMatrix; + m_invProjectionMatrix = invProjectionMatrix; + m_invViewMatrix = invViewMatrix; + + m_viewProjMatrix = m_viewMatrix * m_projectionMatrix; + m_invViewProjMatrix = m_invProjectionMatrix * m_invViewMatrix; + } + + inline void ViewerInstance::UpdateProjViewMatrices(const Matrix4f& projectionMatrix, const Matrix4f& invProjectionMatrix, const Matrix4f& viewMatrix, const Matrix4f& invViewMatrix, const Matrix4f& viewProjMatrix, const Matrix4f& invViewProjMatrix) + { + m_projectionMatrix = projectionMatrix; + m_viewMatrix = viewMatrix; + m_invProjectionMatrix = invProjectionMatrix; + m_invViewMatrix = invViewMatrix; + + m_viewProjMatrix = viewProjMatrix; + m_invViewProjMatrix = invViewProjMatrix; + } + + inline void ViewerInstance::UpdateTargetSize(const Vector2f& targetSize) + { + m_targetSize = targetSize; + } + + inline void ViewerInstance::UpdateViewMatrix(const Matrix4f& viewMatrix) + { + m_viewMatrix = viewMatrix; + if (!m_viewMatrix.GetInverseAffine(&m_invViewMatrix)) + NazaraError("failed to inverse view matrix"); + + m_viewProjMatrix = m_viewMatrix * m_projectionMatrix; + m_invViewProjMatrix = m_invProjectionMatrix * m_invViewMatrix; + } + + inline void ViewerInstance::UpdateViewMatrix(const Matrix4f& viewMatrix, const Matrix4f& invViewMatrix) + { + m_viewMatrix = viewMatrix; + m_invViewMatrix = invViewMatrix; + + m_viewProjMatrix = m_viewMatrix * m_projectionMatrix; + m_invViewProjMatrix = m_invProjectionMatrix * m_invViewMatrix; + } +} + +#include diff --git a/src/Nazara/Graphics/ViewerInstance.cpp b/src/Nazara/Graphics/ViewerInstance.cpp new file mode 100644 index 000000000..c0f6bc2d5 --- /dev/null +++ b/src/Nazara/Graphics/ViewerInstance.cpp @@ -0,0 +1,46 @@ +// Copyright (C) 2017 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 + +namespace Nz +{ + ViewerInstance::ViewerInstance() : + m_invProjectionMatrix(Nz::Matrix4f::Identity()), + m_invViewProjMatrix(Nz::Matrix4f::Identity()), + m_invViewMatrix(Nz::Matrix4f::Identity()), + m_projectionMatrix(Nz::Matrix4f::Identity()), + m_viewProjMatrix(Nz::Matrix4f::Identity()), + m_viewMatrix(Nz::Matrix4f::Identity()), + m_targetSize(Nz::Vector2f(0.f, 0.f)) + { + } + + void ViewerInstance::UpdateViewBuffer(UploadPool& uploadPool, CommandBufferBuilder& builder) + { + Nz::PredefinedViewerData viewerDataOffsets = Nz::PredefinedViewerData::GetOffsets(); + + auto& allocation = uploadPool.Allocate(viewerDataOffsets.totalSize); + Nz::AccessByOffset(allocation.mappedPtr, viewerDataOffsets.eyePositionOffset) = m_viewMatrix.GetTranslation(); + Nz::AccessByOffset(allocation.mappedPtr, viewerDataOffsets.invTargetSizeOffset) = 1.f / m_targetSize; + Nz::AccessByOffset(allocation.mappedPtr, viewerDataOffsets.targetSizeOffset) = m_targetSize; + + Nz::AccessByOffset(allocation.mappedPtr, viewerDataOffsets.invProjMatrixOffset) = m_invProjectionMatrix; + Nz::AccessByOffset(allocation.mappedPtr, viewerDataOffsets.invViewMatrixOffset) = m_invViewMatrix; + Nz::AccessByOffset(allocation.mappedPtr, viewerDataOffsets.invViewProjMatrixOffset) = m_invViewProjMatrix; + Nz::AccessByOffset(allocation.mappedPtr, viewerDataOffsets.projMatrixOffset) = m_projectionMatrix; + Nz::AccessByOffset(allocation.mappedPtr, viewerDataOffsets.viewProjMatrixOffset) = m_viewProjMatrix; + Nz::AccessByOffset(allocation.mappedPtr, viewerDataOffsets.viewMatrixOffset) = m_viewMatrix; + + const std::shared_ptr& instanceDataUBO = Graphics::Instance()->GetViewerDataUBO(); + builder.CopyBuffer(allocation, instanceDataUBO.get()); + } +}