diff --git a/include/Nazara/Renderer/RenderWindow.hpp b/include/Nazara/Renderer/RenderWindow.hpp index 41c2e6412..9f0a74fd8 100644 --- a/include/Nazara/Renderer/RenderWindow.hpp +++ b/include/Nazara/Renderer/RenderWindow.hpp @@ -11,13 +11,16 @@ #include #include +#include +#include #include #include #include #include +#include +class NzAbstractImage; class NzContext; -class NzImage; class NzTexture; struct NzContextParameters; @@ -29,8 +32,8 @@ class NAZARA_API NzRenderWindow : public NzRenderTarget, public NzWindow NzRenderWindow(NzWindowHandle handle, const NzContextParameters& parameters = NzContextParameters()); virtual ~NzRenderWindow(); - bool CopyToImage(NzImage* image) const; - bool CopyToTexture(NzTexture* texture) const; + bool CopyToImage(NzAbstractImage* image, const NzVector3ui& dstPos = NzVector3ui(0U)) const; + bool CopyToImage(NzAbstractImage* image, const NzRectui& rect, const NzVector3ui& dstPos = NzVector3ui(0U)) const; bool Create(NzVideoMode mode, const NzString& title, nzUInt32 style = nzWindowStyle_Default, const NzContextParameters& parameters = NzContextParameters()); bool Create(NzWindowHandle handle, const NzContextParameters& parameters = NzContextParameters()); @@ -61,6 +64,7 @@ class NAZARA_API NzRenderWindow : public NzRenderTarget, public NzWindow void OnWindowDestroy() override; void OnWindowResized() override; + mutable std::vector m_buffer; NzClock m_clock; NzContextParameters m_parameters; mutable NzContext* m_context = nullptr; diff --git a/src/Nazara/Renderer/RenderWindow.cpp b/src/Nazara/Renderer/RenderWindow.cpp index 3da301254..479fdb2ff 100644 --- a/src/Nazara/Renderer/RenderWindow.cpp +++ b/src/Nazara/Renderer/RenderWindow.cpp @@ -13,8 +13,6 @@ #include #include -///TODO: Améliorer les méthode CopyTo* - NzRenderWindow::NzRenderWindow(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters) { NzErrorFlags flags(nzErrorFlag_ThrowException, true); @@ -33,7 +31,7 @@ NzRenderWindow::~NzRenderWindow() OnWindowDestroy(); } -bool NzRenderWindow::CopyToImage(NzImage* image) const +bool NzRenderWindow::CopyToImage(NzAbstractImage* image, const NzVector3ui& dstPos) const { #if NAZARA_RENDERER_SAFE if (!m_context) @@ -41,63 +39,47 @@ bool NzRenderWindow::CopyToImage(NzImage* image) const NazaraError("Window has not been created"); return false; } + #endif + return CopyToImage(image, NzRectui(NzVector2ui(0U), GetSize())); +} + +bool NzRenderWindow::CopyToImage(NzAbstractImage* image, const NzRectui& rect, const NzVector3ui& dstPos) const +{ + #if NAZARA_RENDERER_SAFE + if (!m_context) + { + NazaraError("Window has not been created"); + return false; + } + #endif + + NzVector2ui windowSize = GetSize(); + + #if NAZARA_RENDERER_SAFE if (!image) { NazaraError("Image must be valid"); return false; } - #endif - const NzContext* currentContext = NzContext::GetCurrent(); - if (m_context != currentContext) + if (image->GetFormat() != nzPixelFormat_RGBA8) { - if (!m_context->SetActive(true)) - { - NazaraError("Failed to activate context"); - return false; - } - } - - NzVector2ui size = GetSize(); - - if (!image->Create(nzImageType_2D, nzPixelFormat_RGBA8, size.x, size.y, 1, 1)) - { - NazaraError("Failed to create image"); + // Pour plus de facilité, évidemment on peut faire sauter cette règle avec un peu de gestion + NazaraError("Image must be RGBA8-formatted"); return false; } - nzUInt8* pixels = image->GetPixels(); - glReadPixels(0, 0, size.x, size.y, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - image->FlipVertically(); - - if (m_context != currentContext) + if (rect.x + rect.width > windowSize.x || rect.y + rect.height > windowSize.y) { - if (currentContext) - { - if (!currentContext->SetActive(true)) - NazaraWarning("Failed to reset current context"); - } - else - m_context->SetActive(false); - } - - return true; -} - -bool NzRenderWindow::CopyToTexture(NzTexture* texture) const -{ - #if NAZARA_RENDERER_SAFE - if (!m_context) - { - NazaraError("Window has not been created"); + NazaraError("Rectangle dimensions are out of window's bounds"); return false; } - if (!texture) + NzVector3ui imageSize = image->GetSize(); + if (dstPos.x + rect.width > imageSize.x || dstPos.y + rect.height > imageSize.y || dstPos.z > imageSize.z) { - NazaraError("Texture must be valid"); + NazaraError("Cube dimensions are out of image's bounds"); return false; } #endif @@ -112,22 +94,21 @@ bool NzRenderWindow::CopyToTexture(NzTexture* texture) const } } - NzVector2ui size = GetSize(); + ///TODO: Fast-path pour les images en cas de copie du buffer entier - if (!texture->Create(nzImageType_2D, nzPixelFormat_RGBA8, size.x, size.y, 1, 1)) - { - NazaraError("Failed to create texture"); - return false; - } + m_buffer.resize(rect.width*rect.height*4); + glReadPixels(rect.x, windowSize.y - rect.height - rect.y, rect.width, rect.height, GL_RGBA, GL_UNSIGNED_BYTE, m_buffer.data()); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, size.x, size.y); + // Les pixels sont retournés, nous devons envoyer les pixels par rangée + for (unsigned int i = 0; i < rect.height; ++i) + image->Update(&m_buffer[rect.width*4*i], NzBoxui(dstPos.x, rect.height - i - 1, dstPos.z, rect.width, 1, 1), rect.width); if (m_context != currentContext) { if (currentContext) { if (!currentContext->SetActive(true)) - NazaraWarning("Failed to reset current context"); + NazaraWarning("Failed to reset old context"); } else m_context->SetActive(false); @@ -136,6 +117,7 @@ bool NzRenderWindow::CopyToTexture(NzTexture* texture) const return true; } + bool NzRenderWindow::Create(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters) { m_parameters = parameters;