Added CopyTo(Image/Texture) to NzRenderWindow

Added several methods to NzRenderer
Optimized NzRenderer::GetMax*();
Nz(Render)Window::GetSize now returns an unsigned vector
Fixed textures being flipped
This commit is contained in:
Lynix 2012-06-05 23:06:47 +02:00
parent a176648265
commit ddd2a2f310
13 changed files with 619 additions and 229 deletions

View File

@ -74,6 +74,7 @@ NAZARA_API extern PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
NAZARA_API extern PFNGLCOLORMASKPROC glColorMask; NAZARA_API extern PFNGLCOLORMASKPROC glColorMask;
NAZARA_API extern PFNGLCULLFACEPROC glCullFace; NAZARA_API extern PFNGLCULLFACEPROC glCullFace;
NAZARA_API extern PFNGLCOMPILESHADERPROC glCompileShader; NAZARA_API extern PFNGLCOMPILESHADERPROC glCompileShader;
NAZARA_API extern PFNGLCOPYTEXSUBIMAGE2DPROC glCopyTexSubImage2D;
NAZARA_API extern PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControl; NAZARA_API extern PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControl;
NAZARA_API extern PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsert; NAZARA_API extern PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsert;
NAZARA_API extern PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallback; NAZARA_API extern PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallback;
@ -130,6 +131,7 @@ NAZARA_API extern PFNGLLINKPROGRAMPROC glLinkProgram;
NAZARA_API extern PFNGLMAPBUFFERPROC glMapBuffer; NAZARA_API extern PFNGLMAPBUFFERPROC glMapBuffer;
NAZARA_API extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange; NAZARA_API extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
NAZARA_API extern PFNGLPOLYGONMODEPROC glPolygonMode; NAZARA_API extern PFNGLPOLYGONMODEPROC glPolygonMode;
NAZARA_API extern PFNGLREADPIXELSPROC glReadPixels;
NAZARA_API extern PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage; NAZARA_API extern PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage;
NAZARA_API extern PFNGLSCISSORPROC glScissor; NAZARA_API extern PFNGLSCISSORPROC glScissor;
NAZARA_API extern PFNGLSHADERSOURCEPROC glShaderSource; NAZARA_API extern PFNGLSHADERSOURCEPROC glShaderSource;

View File

@ -19,10 +19,14 @@
#endif #endif
class NzContext; class NzContext;
class NzImage;
class NzTexture;
struct NzContextParameters; struct NzContextParameters;
class NAZARA_API NzRenderWindow : public NzRenderTarget, public NzWindow class NAZARA_API NzRenderWindow : public NzRenderTarget, public NzWindow
{ {
friend class NzTexture;
public: public:
NzRenderWindow(); NzRenderWindow();
NzRenderWindow(NzVideoMode mode, const NzString& title, nzUInt32 style = NzWindow::Default, const NzContextParameters& parameters = NzContextParameters()); NzRenderWindow(NzVideoMode mode, const NzString& title, nzUInt32 style = NzWindow::Default, const NzContextParameters& parameters = NzContextParameters());
@ -31,6 +35,9 @@ class NAZARA_API NzRenderWindow : public NzRenderTarget, public NzWindow
bool CanActivate() const; bool CanActivate() const;
bool CopyToImage(NzImage* image); ///TODO: Const
bool CopyToTexture(NzTexture* texture); ///TODO: Const
bool Create(NzVideoMode mode, const NzString& title, nzUInt32 style = NzWindow::Default, const NzContextParameters& parameters = NzContextParameters()); bool Create(NzVideoMode mode, const NzString& title, nzUInt32 style = NzWindow::Default, const NzContextParameters& parameters = NzContextParameters());
bool Create(NzWindowHandle handle, const NzContextParameters& parameters = NzContextParameters()); bool Create(NzWindowHandle handle, const NzContextParameters& parameters = NzContextParameters());

View File

@ -13,6 +13,34 @@
#define NazaraRenderer NzRenderer::Instance() #define NazaraRenderer NzRenderer::Instance()
enum nzBlendFunc
{
nzBlendFunc_DestAlpha,
nzBlendFunc_DestColor,
nzBlendFunc_SrcAlpha,
nzBlendFunc_SrcColor,
nzBlendFunc_InvDestAlpha,
nzBlendFunc_InvDestColor,
nzBlendFunc_InvSrcAlpha,
nzBlendFunc_InvSrcColor,
nzBlendFunc_One,
nzBlendFunc_Zero
};
enum nzFaceCulling
{
nzFaceCulling_Back,
nzFaceCulling_Front,
nzFaceCulling_FrontAndBack
};
enum nzFaceFilling
{
nzFaceFilling_Point,
nzFaceFilling_Line,
nzFaceFilling_Fill
};
enum nzPrimitiveType enum nzPrimitiveType
{ {
nzPrimitiveType_LineList, nzPrimitiveType_LineList,
@ -46,6 +74,40 @@ enum nzRendererClear
nzRendererClear_Stencil = 0x04 nzRendererClear_Stencil = 0x04
}; };
enum nzRendererComparison
{
nzRendererComparison_Always,
nzRendererComparison_Equal,
nzRendererComparison_Greater,
nzRendererComparison_GreaterOrEqual,
nzRendererComparison_Less,
nzRendererComparison_LessOrEqual,
nzRendererComparison_Never
};
enum nzRendererParameter
{
nzRendererParameter_AlphaTest,
nzRendererParameter_Blend,
nzRendererParameter_ColorWrite,
nzRendererParameter_DepthTest,
nzRendererParameter_DepthWrite,
nzRendererParameter_FaceCulling,
nzRendererParameter_Stencil
};
enum nzStencilOperation
{
nzStencilOperation_Decrement,
nzStencilOperation_DecrementToSaturation,
nzStencilOperation_Increment,
nzStencilOperation_IncrementToSaturation,
nzStencilOperation_Invert,
nzStencilOperation_Keep,
nzStencilOperation_Replace,
nzStencilOperation_Zero
};
class NzColor; class NzColor;
class NzContext; class NzContext;
class NzIndexBuffer; class NzIndexBuffer;
@ -66,6 +128,10 @@ class NAZARA_API NzRenderer
void DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int firstIndex, unsigned int indexCount); void DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int firstIndex, unsigned int indexCount);
void DrawPrimitives(nzPrimitiveType primitive, unsigned int firstVertex, unsigned int vertexCount); void DrawPrimitives(nzPrimitiveType primitive, unsigned int firstVertex, unsigned int vertexCount);
void Enable(nzRendererParameter parameter, bool enable);
unsigned int GetMaxAnisotropyLevel() const;
unsigned int GetMaxRenderTargets() const;
unsigned int GetMaxTextureUnits() const; unsigned int GetMaxTextureUnits() const;
NzShader* GetShader() const; NzShader* GetShader() const;
NzRenderTarget* GetTarget() const; NzRenderTarget* GetTarget() const;
@ -77,8 +143,16 @@ class NAZARA_API NzRenderer
void SetClearColor(nzUInt8 r, nzUInt8 g, nzUInt8 b, nzUInt8 a = 255); void SetClearColor(nzUInt8 r, nzUInt8 g, nzUInt8 b, nzUInt8 a = 255);
void SetClearDepth(double depth); void SetClearDepth(double depth);
void SetClearStencil(unsigned int value); void SetClearStencil(unsigned int value);
void SetFaceCulling(nzFaceCulling cullingMode);
void SetFaceFilling(nzFaceFilling fillingMode);
bool SetIndexBuffer(const NzIndexBuffer* indexBuffer); bool SetIndexBuffer(const NzIndexBuffer* indexBuffer);
bool SetShader(NzShader* shader); bool SetShader(NzShader* shader);
void SetStencilCompareFunction(nzRendererComparison compareFunc);
void SetStencilFailOperation(nzStencilOperation failOperation);
void SetStencilMask(nzUInt32 mask);
void SetStencilPassOperation(nzStencilOperation passOperation);
void SetStencilReferenceValue(unsigned int refValue);
void SetStencilZFailOperation(nzStencilOperation zfailOperation);
bool SetTarget(NzRenderTarget* target); bool SetTarget(NzRenderTarget* target);
bool SetVertexBuffer(const NzVertexBuffer* vertexBuffer); bool SetVertexBuffer(const NzVertexBuffer* vertexBuffer);
bool SetVertexDeclaration(const NzVertexDeclaration* vertexDeclaration); bool SetVertexDeclaration(const NzVertexDeclaration* vertexDeclaration);
@ -89,19 +163,30 @@ class NAZARA_API NzRenderer
static bool IsInitialized(); static bool IsInitialized();
private: private:
bool UpdateStates(); bool EnsureStateUpdate();
typedef std::tuple<const NzContext*, const NzIndexBuffer*, const NzVertexBuffer*, const NzVertexDeclaration*> VAO_Key; typedef std::tuple<const NzContext*, const NzIndexBuffer*, const NzVertexBuffer*, const NzVertexDeclaration*> VAO_Key;
std::map<VAO_Key, unsigned int> m_vaos; std::map<VAO_Key, unsigned int> m_vaos;
nzRendererComparison m_stencilCompare;
nzStencilOperation m_stencilFail;
nzStencilOperation m_stencilPass;
nzStencilOperation m_stencilZFail;
nzUInt32 m_stencilMask;
const NzIndexBuffer* m_indexBuffer; const NzIndexBuffer* m_indexBuffer;
NzRenderTarget* m_target; NzRenderTarget* m_target;
NzShader* m_shader; NzShader* m_shader;
NzUtility* m_utilityModule; NzUtility* m_utilityModule;
const NzVertexBuffer* m_vertexBuffer; const NzVertexBuffer* m_vertexBuffer;
const NzVertexDeclaration* m_vertexDeclaration; const NzVertexDeclaration* m_vertexDeclaration;
bool m_vaoUpdated;
bool m_capabilities[nzRendererCap_Count]; bool m_capabilities[nzRendererCap_Count];
bool m_statesUpdated; bool m_stencilFuncUpdated;
bool m_stencilOpUpdated;
unsigned int m_maxAnisotropyLevel;
unsigned int m_maxRenderTarget;
unsigned int m_maxTextureUnit;
unsigned int m_stencilReference;
static NzRenderer* s_instance; static NzRenderer* s_instance;
static bool s_initialized; static bool s_initialized;

View File

@ -27,7 +27,7 @@ enum nzTextureWrap
nzTextureWrap_Unknown nzTextureWrap_Unknown
}; };
class NzRenderWindow; ///TODO: Screenshot class NzShader;
struct NzTextureImpl; struct NzTextureImpl;
class NAZARA_API NzTexture : public NzResource, NzNonCopyable class NAZARA_API NzTexture : public NzResource, NzNonCopyable

View File

@ -61,7 +61,7 @@ class NAZARA_API NzWindow : NzNonCopyable
NzWindowHandle GetHandle() const; NzWindowHandle GetHandle() const;
unsigned int GetHeight() const; unsigned int GetHeight() const;
NzVector2i GetPosition() const; NzVector2i GetPosition() const;
NzVector2i GetSize() const; NzVector2ui GetSize() const;
NzString GetTitle() const; NzString GetTitle() const;
unsigned int GetWidth() const; unsigned int GetWidth() const;

View File

@ -223,6 +223,7 @@ bool NzOpenGL::Initialize()
glColorMask = reinterpret_cast<PFNGLCOLORMASKPROC>(LoadEntry("glColorMask")); glColorMask = reinterpret_cast<PFNGLCOLORMASKPROC>(LoadEntry("glColorMask"));
glCullFace = reinterpret_cast<PFNGLCULLFACEPROC>(LoadEntry("glCullFace")); glCullFace = reinterpret_cast<PFNGLCULLFACEPROC>(LoadEntry("glCullFace"));
glCompileShader = reinterpret_cast<PFNGLCOMPILESHADERPROC>(LoadEntry("glCompileShader")); glCompileShader = reinterpret_cast<PFNGLCOMPILESHADERPROC>(LoadEntry("glCompileShader"));
glCopyTexSubImage2D = reinterpret_cast<PFNGLCOPYTEXSUBIMAGE2DPROC>(LoadEntry("glCopyTexSubImage2D"));
glDeleteBuffers = reinterpret_cast<PFNGLDELETEBUFFERSPROC>(LoadEntry("glDeleteBuffers")); glDeleteBuffers = reinterpret_cast<PFNGLDELETEBUFFERSPROC>(LoadEntry("glDeleteBuffers"));
glDeleteQueries = reinterpret_cast<PFNGLDELETEQUERIESPROC>(LoadEntry("glDeleteQueries")); glDeleteQueries = reinterpret_cast<PFNGLDELETEQUERIESPROC>(LoadEntry("glDeleteQueries"));
glDeleteProgram = reinterpret_cast<PFNGLDELETEPROGRAMPROC>(LoadEntry("glDeleteProgram")); glDeleteProgram = reinterpret_cast<PFNGLDELETEPROGRAMPROC>(LoadEntry("glDeleteProgram"));
@ -263,6 +264,7 @@ bool NzOpenGL::Initialize()
glLinkProgram = reinterpret_cast<PFNGLLINKPROGRAMPROC>(LoadEntry("glLinkProgram")); glLinkProgram = reinterpret_cast<PFNGLLINKPROGRAMPROC>(LoadEntry("glLinkProgram"));
glMapBuffer = reinterpret_cast<PFNGLMAPBUFFERPROC>(LoadEntry("glMapBuffer")); glMapBuffer = reinterpret_cast<PFNGLMAPBUFFERPROC>(LoadEntry("glMapBuffer"));
glPolygonMode = reinterpret_cast<PFNGLPOLYGONMODEPROC>(LoadEntry("glPolygonMode")); glPolygonMode = reinterpret_cast<PFNGLPOLYGONMODEPROC>(LoadEntry("glPolygonMode"));
glReadPixels = reinterpret_cast<PFNGLREADPIXELSPROC>(LoadEntry("glReadPixels"));
glScissor = reinterpret_cast<PFNGLSCISSORPROC>(LoadEntry("glScissor")); glScissor = reinterpret_cast<PFNGLSCISSORPROC>(LoadEntry("glScissor"));
glShaderSource = reinterpret_cast<PFNGLSHADERSOURCEPROC>(LoadEntry("glShaderSource")); glShaderSource = reinterpret_cast<PFNGLSHADERSOURCEPROC>(LoadEntry("glShaderSource"));
glStencilFunc = reinterpret_cast<PFNGLSTENCILFUNCPROC>(LoadEntry("glStencilFunc")); glStencilFunc = reinterpret_cast<PFNGLSTENCILFUNCPROC>(LoadEntry("glStencilFunc"));
@ -545,6 +547,7 @@ PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus = nullptr;
PFNGLCOLORMASKPROC glColorMask = nullptr; PFNGLCOLORMASKPROC glColorMask = nullptr;
PFNGLCULLFACEPROC glCullFace = nullptr; PFNGLCULLFACEPROC glCullFace = nullptr;
PFNGLCOMPILESHADERPROC glCompileShader = nullptr; PFNGLCOMPILESHADERPROC glCompileShader = nullptr;
PFNGLCOPYTEXSUBIMAGE2DPROC glCopyTexSubImage2D = nullptr;
PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControl = nullptr; PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControl = nullptr;
PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsert = nullptr; PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsert = nullptr;
PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallback = nullptr; PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallback = nullptr;
@ -601,6 +604,7 @@ PFNGLLINKPROGRAMPROC glLinkProgram = nullptr;
PFNGLMAPBUFFERPROC glMapBuffer = nullptr; PFNGLMAPBUFFERPROC glMapBuffer = nullptr;
PFNGLMAPBUFFERRANGEPROC glMapBufferRange = nullptr; PFNGLMAPBUFFERRANGEPROC glMapBufferRange = nullptr;
PFNGLPOLYGONMODEPROC glPolygonMode = nullptr; PFNGLPOLYGONMODEPROC glPolygonMode = nullptr;
PFNGLREADPIXELSPROC glReadPixels = nullptr;
PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage = nullptr; PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage = nullptr;
PFNGLSCISSORPROC glScissor = nullptr; PFNGLSCISSORPROC glScissor = nullptr;
PFNGLSHADERSOURCEPROC glShaderSource = nullptr; PFNGLSHADERSOURCEPROC glShaderSource = nullptr;

View File

@ -8,15 +8,10 @@
#include <Nazara/Renderer/Config.hpp> #include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/Context.hpp> #include <Nazara/Renderer/Context.hpp>
#include <Nazara/Renderer/ContextParameters.hpp> #include <Nazara/Renderer/ContextParameters.hpp>
#include <Nazara/Renderer/Texture.hpp>
#include <stdexcept> #include <stdexcept>
#include <Nazara/Renderer/Debug.hpp> #include <Nazara/Renderer/Debug.hpp>
namespace
{
NzContextParameters invalidContextParameters;
NzRenderTargetParameters invalidRTParameters;
}
NzRenderWindow::NzRenderWindow() : NzRenderWindow::NzRenderWindow() :
m_context(nullptr) m_context(nullptr)
{ {
@ -59,6 +54,82 @@ bool NzRenderWindow::CanActivate() const
return m_impl != nullptr && m_context != nullptr; return m_impl != nullptr && m_context != nullptr;
} }
bool NzRenderWindow::CopyToImage(NzImage* image)
{
#if NAZARA_RENDERER_SAFE
if (!m_context)
{
NazaraError("Window has not been created");
return false;
}
if (!image)
{
NazaraError("Image must be valid");
return false;
}
#endif
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");
return false;
}
nzUInt8* pixels = image->GetPixels();
glReadPixels(0, 0, size.x, size.y, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
for (unsigned int j = 0; j < size.y/2; ++j)
std::swap_ranges(&pixels[j*size.x*4], &pixels[(j+1)*size.x*4-1], &pixels[(size.y-j-1)*size.x*4]);
return true;
}
bool NzRenderWindow::CopyToTexture(NzTexture* texture)
{
#if NAZARA_RENDERER_SAFE
if (!m_context)
{
NazaraError("Window has not been created");
return false;
}
if (!texture)
{
NazaraError("Texture must be valid");
return false;
}
#endif
if (!m_context->SetActive(true))
{
NazaraError("Failed to activate context");
return false;
}
NzVector2ui size = GetSize();
if (!texture->Create(nzImageType_2D, nzPixelFormat_RGBA8, size.x, size.y, 1, 1, true))
{
NazaraError("Failed to create texture");
return false;
}
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, size.x, size.y);
texture->Unlock();
return true;
}
bool NzRenderWindow::Create(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters) bool NzRenderWindow::Create(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters)
{ {
m_parameters = parameters; m_parameters = parameters;
@ -81,29 +152,29 @@ void NzRenderWindow::EnableVerticalSync(bool enabled)
{ {
if (m_context) if (m_context)
{ {
#if defined(NAZARA_PLATFORM_WINDOWS) #if defined(NAZARA_PLATFORM_WINDOWS)
if (!m_context->SetActive(true)) if (!m_context->SetActive(true))
{ {
NazaraError("Unable to activate context"); NazaraError("Failed to activate context");
return; return;
} }
if (wglSwapInterval) if (wglSwapInterval)
wglSwapInterval(enabled ? 1 : 0); wglSwapInterval(enabled ? 1 : 0);
else else
#elif defined(NAZARA_PLATFORM_LINUX) #elif defined(NAZARA_PLATFORM_LINUX)
if (!m_context->SetActive(true)) if (!m_context->SetActive(true))
{ {
NazaraError("Unable to activate context"); NazaraError("Failed to activate context");
return; return;
} }
if (glXSwapInterval) if (glXSwapInterval)
glXSwapInterval(enabled ? 1 : 0); glXSwapInterval(enabled ? 1 : 0);
else else
#else #else
#error Vertical Sync is not supported on this platform #error Vertical Sync is not supported on this platform
#endif #endif
NazaraError("Vertical Sync is not supported on this platform"); NazaraError("Vertical Sync is not supported on this platform");
} }
else else

View File

@ -30,6 +30,21 @@ namespace
4 // nzElementUsage_TexCoord 4 // nzElementUsage_TexCoord
}; };
const GLenum faceCullingMode[] =
{
GL_BACK, // nzFaceCulling_Back
GL_FRONT, // nzFaceCulling_Front
GL_FRONT_AND_BACK // nzFaceCulling_FrontAndBack
};
const GLenum faceFillingMode[] =
{
GL_POINT, // nzFaceFilling_Point
GL_LINE, // nzFaceFilling_Line
GL_FILL // nzFaceFilling_Fill
};
const GLenum openglPrimitive[] = const GLenum openglPrimitive[] =
{ {
GL_LINES, // nzPrimitiveType_LineList, GL_LINES, // nzPrimitiveType_LineList,
@ -65,15 +80,42 @@ namespace
GL_FLOAT, // nzElementType_Float3 GL_FLOAT, // nzElementType_Float3
GL_FLOAT // nzElementType_Float4 GL_FLOAT // nzElementType_Float4
}; };
const GLenum rendererComparison[] =
{
GL_ALWAYS, // nzRendererComparison_Always
GL_EQUAL, // nzRendererComparison_Equal
GL_GREATER, // nzRendererComparison_Greater
GL_GEQUAL, // nzRendererComparison_GreaterOrEqual
GL_LESS, // nzRendererComparison_Less
GL_LEQUAL, // nzRendererComparison_LessOrEqual
GL_NEVER // nzRendererComparison_Never
};
const GLenum rendererParameter[] =
{
GL_BLEND, // nzRendererParameter_Blend
GL_NONE, // nzRendererParameter_ColorWrite
GL_DEPTH_TEST, // nzRendererParameter_DepthTest
GL_NONE, // nzRendererParameter_DepthWrite
GL_CULL_FACE, // nzRendererParameter_FaceCulling
GL_STENCIL_TEST // nzRendererParameter_Stencil
};
const GLenum stencilOperation[] =
{
GL_DECR, // nzStencilOperation_Decrement
GL_DECR_WRAP, // nzStencilOperation_DecrementToSaturation
GL_INCR, // nzStencilOperation_Increment
GL_INCR_WRAP, // nzStencilOperation_IncrementToSaturation
GL_INVERT, // nzStencilOperation_Invert
GL_KEEP, // nzStencilOperation_Keep
GL_REPLACE, // nzStencilOperation_Replace
GL_ZERO // nzStencilOperation_Zero
};
} }
NzRenderer::NzRenderer() : NzRenderer::NzRenderer()
m_indexBuffer(nullptr),
m_target(nullptr),
m_shader(nullptr),
m_vertexBuffer(nullptr),
m_vertexDeclaration(nullptr),
m_statesUpdated(false)
{ {
#if NAZARA_RENDERER_SAFE #if NAZARA_RENDERER_SAFE
if (s_instance) if (s_instance)
@ -121,6 +163,12 @@ void NzRenderer::Clear(unsigned long flags)
void NzRenderer::DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int firstIndex, unsigned int indexCount) void NzRenderer::DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int firstIndex, unsigned int indexCount)
{ {
#ifdef NAZARA_DEBUG #ifdef NAZARA_DEBUG
if (NzContext::GetCurrent() == nullptr)
{
NazaraError("No active context");
return;
}
if (!m_indexBuffer) if (!m_indexBuffer)
{ {
NazaraError("No index buffer"); NazaraError("No index buffer");
@ -128,14 +176,11 @@ void NzRenderer::DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int f
} }
#endif #endif
if (!m_statesUpdated) if (!EnsureStateUpdate())
{
if (!UpdateStates())
{ {
NazaraError("Failed to update states"); NazaraError("Failed to update states");
return; return;
} }
}
nzUInt8 indexSize = m_indexBuffer->GetIndexSize(); nzUInt8 indexSize = m_indexBuffer->GetIndexSize();
@ -164,30 +209,58 @@ void NzRenderer::DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int f
void NzRenderer::DrawPrimitives(nzPrimitiveType primitive, unsigned int firstVertex, unsigned int vertexCount) void NzRenderer::DrawPrimitives(nzPrimitiveType primitive, unsigned int firstVertex, unsigned int vertexCount)
{ {
if (!m_statesUpdated) #ifdef NAZARA_DEBUG
if (NzContext::GetCurrent() == nullptr)
{ {
if (!UpdateStates()) NazaraError("No active context");
return;
}
#endif
if (!EnsureStateUpdate())
{ {
NazaraError("Failed to update states"); NazaraError("Failed to update states");
return; return;
} }
}
glDrawArrays(openglPrimitive[primitive], firstVertex, vertexCount); glDrawArrays(openglPrimitive[primitive], firstVertex, vertexCount);
} }
void NzRenderer::Enable(nzRendererParameter parameter, bool enable)
{
switch (parameter)
{
case nzRendererParameter_ColorWrite:
glColorMask(enable, enable, enable, enable);
break;
case nzRendererParameter_DepthWrite:
glDepthMask(enable);
break;
default:
if (enable)
glEnable(rendererParameter[parameter]);
else
glDisable(rendererParameter[parameter]);
break;
}
}
unsigned int NzRenderer::GetMaxAnisotropyLevel() const
{
return m_maxAnisotropyLevel;
}
unsigned int NzRenderer::GetMaxRenderTargets() const
{
return m_maxRenderTarget;
}
unsigned int NzRenderer::GetMaxTextureUnits() const unsigned int NzRenderer::GetMaxTextureUnits() const
{ {
static int maxTextureUnits = -1; return m_maxTextureUnit;
if (maxTextureUnits == -1)
{
if (m_capabilities[nzRendererCap_TextureMulti])
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
else
maxTextureUnits = 1;
}
return maxTextureUnits;
} }
NzShader* NzRenderer::GetShader() const NzShader* NzRenderer::GetShader() const
@ -224,6 +297,22 @@ bool NzRenderer::Initialize()
if (NzOpenGL::Initialize()) if (NzOpenGL::Initialize())
{ {
m_vaoUpdated = false;
m_indexBuffer = nullptr;
m_shader = nullptr;
m_stencilCompare = nzRendererComparison_Always;
m_stencilFail = nzStencilOperation_Keep;
m_stencilFuncUpdated = true;
m_stencilMask = 0xFFFFFFFF;
m_stencilOpUpdated = true;
m_stencilPass = nzStencilOperation_Keep;
m_stencilReference = 0;
m_stencilZFail = nzStencilOperation_Keep;
m_target = nullptr;
m_vertexBuffer = nullptr;
m_vertexDeclaration = nullptr;
// Récupération des capacités
m_capabilities[nzRendererCap_AnisotropicFilter] = NzOpenGL::IsSupported(NzOpenGL::AnisotropicFilter); m_capabilities[nzRendererCap_AnisotropicFilter] = NzOpenGL::IsSupported(NzOpenGL::AnisotropicFilter);
m_capabilities[nzRendererCap_FP64] = NzOpenGL::IsSupported(NzOpenGL::FP64); m_capabilities[nzRendererCap_FP64] = NzOpenGL::IsSupported(NzOpenGL::FP64);
m_capabilities[nzRendererCap_HardwareBuffer] = true; // Natif depuis OpenGL 1.5 m_capabilities[nzRendererCap_HardwareBuffer] = true; // Natif depuis OpenGL 1.5
@ -235,6 +324,40 @@ bool NzRenderer::Initialize()
m_capabilities[nzRendererCap_TextureMulti] = true; // Natif depuis OpenGL 1.3 m_capabilities[nzRendererCap_TextureMulti] = true; // Natif depuis OpenGL 1.3
m_capabilities[nzRendererCap_TextureNPOT] = true; // Natif depuis OpenGL 2.0 m_capabilities[nzRendererCap_TextureNPOT] = true; // Natif depuis OpenGL 2.0
if (m_capabilities[nzRendererCap_AnisotropicFilter])
{
GLint maxAnisotropy;
glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy);
m_maxAnisotropyLevel = static_cast<unsigned int>(maxAnisotropy);
}
else
m_maxAnisotropyLevel = 1;
if (m_capabilities[nzRendererCap_MultipleRenderTargets])
{
// Permettre de gérer plus de targets que de nombre de sorties dans le shader ne servirait à rien
GLint maxDrawBuffers;
glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
GLint maxRenderTextureTargets;
glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxRenderTextureTargets);
m_maxRenderTarget = static_cast<unsigned int>(std::min(maxDrawBuffers, maxRenderTextureTargets));
}
else
m_maxRenderTarget = 1;
if (m_capabilities[nzRendererCap_TextureMulti])
{
GLint maxTextureUnits;
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
m_maxTextureUnit = static_cast<unsigned int>(maxTextureUnits);
}
else
m_maxTextureUnit = 1;
s_initialized = true; s_initialized = true;
return true; return true;
@ -295,12 +418,39 @@ void NzRenderer::SetClearStencil(unsigned int value)
glClearStencil(value); glClearStencil(value);
} }
void NzRenderer::SetFaceCulling(nzFaceCulling cullingMode)
{
#ifdef NAZARA_DEBUG
if (NzContext::GetCurrent() == nullptr)
{
NazaraError("No active context");
return;
}
#endif
glCullFace(faceCullingMode[cullingMode]);
}
void NzRenderer::SetFaceFilling(nzFaceFilling fillingMode)
{
#ifdef NAZARA_DEBUG
if (NzContext::GetCurrent() == nullptr)
{
NazaraError("No active context");
return;
}
#endif
glPolygonMode(GL_FRONT_AND_BACK, faceFillingMode[fillingMode]);
}
bool NzRenderer::SetIndexBuffer(const NzIndexBuffer* indexBuffer) bool NzRenderer::SetIndexBuffer(const NzIndexBuffer* indexBuffer)
{ {
if (indexBuffer != m_indexBuffer) if (indexBuffer != m_indexBuffer)
{ {
m_indexBuffer = indexBuffer; m_indexBuffer = indexBuffer;
m_statesUpdated = false; m_vaoUpdated = false;
} }
return true; return true;
@ -332,13 +482,67 @@ bool NzRenderer::SetShader(NzShader* shader)
NazaraError("Failed to bind shader"); NazaraError("Failed to bind shader");
return false; return false;
} }
m_shader = shader;
} }
m_shader = shader;
return true; return true;
} }
void NzRenderer::SetStencilCompareFunction(nzRendererComparison compareFunc)
{
if (compareFunc != m_stencilCompare)
{
m_stencilCompare = compareFunc;
m_stencilFuncUpdated = false;
}
}
void NzRenderer::SetStencilFailOperation(nzStencilOperation failOperation)
{
if (failOperation != m_stencilFail)
{
m_stencilFail = failOperation;
m_stencilOpUpdated = false;
}
}
void NzRenderer::SetStencilMask(nzUInt32 mask)
{
if (mask != m_stencilMask)
{
m_stencilMask = mask;
m_stencilFuncUpdated = false;
}
}
void NzRenderer::SetStencilPassOperation(nzStencilOperation passOperation)
{
if (passOperation != m_stencilPass)
{
m_stencilPass = passOperation;
m_stencilOpUpdated = false;
}
}
void NzRenderer::SetStencilReferenceValue(unsigned int refValue)
{
if (refValue != m_stencilReference)
{
m_stencilReference = refValue;
m_stencilFuncUpdated = false;
}
}
void NzRenderer::SetStencilZFailOperation(nzStencilOperation zfailOperation)
{
if (zfailOperation != m_stencilZFail)
{
m_stencilZFail = zfailOperation;
m_stencilOpUpdated = false;
}
}
bool NzRenderer::SetTarget(NzRenderTarget* target) bool NzRenderer::SetTarget(NzRenderTarget* target)
{ {
if (target == m_target) if (target == m_target)
@ -378,7 +582,7 @@ bool NzRenderer::SetVertexBuffer(const NzVertexBuffer* vertexBuffer)
if (m_vertexBuffer != vertexBuffer) if (m_vertexBuffer != vertexBuffer)
{ {
m_vertexBuffer = vertexBuffer; m_vertexBuffer = vertexBuffer;
m_statesUpdated = false; m_vaoUpdated = false;
} }
return true; return true;
@ -389,7 +593,7 @@ bool NzRenderer::SetVertexDeclaration(const NzVertexDeclaration* vertexDeclarati
if (m_vertexDeclaration != vertexDeclaration) if (m_vertexDeclaration != vertexDeclaration)
{ {
m_vertexDeclaration = vertexDeclaration; m_vertexDeclaration = vertexDeclaration;
m_statesUpdated = false; m_vaoUpdated = false;
} }
return true; return true;
@ -438,8 +642,22 @@ bool NzRenderer::IsInitialized()
return s_initialized; return s_initialized;
} }
bool NzRenderer::UpdateStates() bool NzRenderer::EnsureStateUpdate()
{ {
if (!m_stencilFuncUpdated)
{
glStencilFunc(rendererComparison[m_stencilCompare], m_stencilReference, m_stencilMask);
m_stencilFuncUpdated = true;
}
if (!m_stencilOpUpdated)
{
glStencilOp(stencilOperation[m_stencilFail], stencilOperation[m_stencilZFail], stencilOperation[m_stencilPass]);
m_stencilOpUpdated = true;
}
if (!m_vaoUpdated)
{
#if NAZARA_RENDERER_SAFE #if NAZARA_RENDERER_SAFE
if (!m_vertexBuffer) if (!m_vertexBuffer)
{ {
@ -528,7 +746,8 @@ bool NzRenderer::UpdateStates()
glBindVertexArray(vao); glBindVertexArray(vao);
} }
m_statesUpdated = true; m_vaoUpdated = true;
}
return true; return true;
} }

View File

@ -6,6 +6,7 @@
#include <Nazara/Renderer/Texture.hpp> #include <Nazara/Renderer/Texture.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <Nazara/Renderer/Renderer.hpp> #include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Renderer/RenderWindow.hpp>
#include <stdexcept> #include <stdexcept>
#include <Nazara/Renderer/Debug.hpp> #include <Nazara/Renderer/Debug.hpp>
@ -459,7 +460,7 @@ bool NzTexture::Download(NzImage* image) const
if (!image) if (!image)
{ {
NazaraError("Cannot download to a null image"); NazaraError("Image must be valid");
return false; return false;
} }
#endif #endif
@ -479,12 +480,40 @@ bool NzTexture::Download(NzImage* image) const
LockTexture(m_impl); LockTexture(m_impl);
unsigned int width = m_impl->width;
unsigned int height = m_impl->height;
unsigned int depth = m_impl->depth;
nzUInt8 bpp = NzPixelFormat::GetBPP(m_impl->format);
nzUInt8* mirrored = new nzUInt8[width*height*depth*bpp];
// Téléchargement... // Téléchargement...
for (nzUInt8 level = 0; level < m_impl->levelCount; ++level) for (nzUInt8 level = 0; level < m_impl->levelCount; ++level)
glGetTexImage(openglTarget[m_impl->type], level, format.dataFormat, format.dataType, image->GetPixels(level)); {
glGetTexImage(openglTarget[m_impl->type], level, format.dataFormat, format.dataType, mirrored);
// Inversion de la texture pour le repère d'OpenGL
///FIXME: Gérer l'inversion dans NzImage, et gérer également les images compressées
unsigned int faceSize = width*height*bpp;
nzUInt8* ptr = mirrored;
for (unsigned int d = 0; d < depth; ++d)
{
for (unsigned int j = 0; j < height/2; ++j)
std::swap_ranges(&ptr[j*width*bpp], &ptr[(j+1)*width*bpp-1], &ptr[(height-j-1)*width*bpp]);
ptr += faceSize;
}
width = std::max(width >> 1, 1U);
height = std::max(height >> 1, 1U);
depth = std::max(depth >> 1, 1U);
}
UnlockTexture(m_impl); UnlockTexture(m_impl);
delete[] mirrored;
return true; return true;
} }
@ -534,12 +563,12 @@ unsigned int NzTexture::GetAnisotropyLevel() const
LockTexture(m_impl); LockTexture(m_impl);
GLfloat anisotropyLevel; GLint anisotropyLevel;
glGetTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &anisotropyLevel); glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &anisotropyLevel);
UnlockTexture(m_impl); UnlockTexture(m_impl);
return static_cast<unsigned int>(anisotropyLevel); return anisotropyLevel;
} }
nzUInt8 NzTexture::GetBPP() const nzUInt8 NzTexture::GetBPP() const
@ -853,7 +882,7 @@ bool NzTexture::SetAnisotropyLevel(unsigned int anistropyLevel)
LockTexture(m_impl); LockTexture(m_impl);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, static_cast<GLfloat>(anistropyLevel)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anistropyLevel);
UnlockTexture(m_impl); UnlockTexture(m_impl);
@ -1058,56 +1087,16 @@ bool NzTexture::Update(const nzUInt8* pixels, nzUInt8 level)
NazaraError("Texture must be valid"); NazaraError("Texture must be valid");
return false; return false;
} }
if (m_impl->type == nzImageType_Cubemap)
{
NazaraError("Update is not designed for cubemaps, use UpdateFace instead");
return false;
}
if (!pixels)
{
NazaraError("Invalid pixel source");
return false;
}
if (level >= m_impl->levelCount)
{
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_impl->levelCount) + ')');
return false;
}
#endif #endif
OpenGLFormat format; if (m_impl->type == nzImageType_3D)
if (!GetOpenGLFormat(m_impl->format, &format))
{ {
NazaraError("Failed to get OpenGL format"); NazaraInternalError("Not implemented yet, sorry");
return false; return false;
//return Update(pixels, NzCube(0, 0, 0, std::max(m_impl->width >> level, 1U), std::max(m_impl->height >> level, 1U), std::max(m_impl->depth >> level, 1U)), level);
} }
else
LockTexture(m_impl); return Update(pixels, NzRectui(0, 0, std::max(m_impl->width >> level, 1U), std::max(m_impl->height >> level, 1U)), 0, level);
switch (m_impl->type)
{
case nzImageType_1D:
glTexSubImage1D(GL_TEXTURE_1D, level, 0, std::max(m_impl->width >> level, 1U), format.dataFormat, format.dataType, pixels);
break;
case nzImageType_2D:
glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, std::max(m_impl->width >> level, 1U), std::max(m_impl->height >> level, 1U), format.dataFormat, format.dataType, pixels);
break;
case nzImageType_3D:
glTexSubImage3D(GL_TEXTURE_3D, level, 0, 0, 0, std::max(m_impl->width >> level, 1U), std::max(m_impl->height >> level, 1U), std::max(m_impl->depth >> level, 1U), format.dataFormat, format.dataType, pixels);
break;
default:
NazaraInternalError("Image type not handled (0x" + NzString::Number(m_impl->type, 16) + ')');
}
UnlockTexture(m_impl);
return true;
} }
bool NzTexture::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z, nzUInt8 level) bool NzTexture::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z, nzUInt8 level)
@ -1163,20 +1152,32 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int
return false; return false;
} }
nzUInt8 bpp = NzPixelFormat::GetBPP(m_impl->format);
// Inversion de la texture pour le repère d'OpenGL
///FIXME: Gérer l'inversion dans NzImage, et gérer également les images compressées
unsigned int size = rect.width*rect.height*bpp;
nzUInt8* mirrored = new nzUInt8[size];
std::memcpy(mirrored, pixels, size);
nzUInt8* ptr = &mirrored[size*z];
for (unsigned int j = 0; j < rect.height/2; ++j)
std::swap_ranges(&ptr[j*rect.width*bpp], &ptr[(j+1)*rect.width*bpp-1], &ptr[(rect.height-j-1)*rect.width*bpp]);
LockTexture(m_impl); LockTexture(m_impl);
switch (m_impl->type) switch (m_impl->type)
{ {
case nzImageType_1D: case nzImageType_1D:
glTexSubImage1D(GL_TEXTURE_1D, level, rect.x, rect.width, format.dataFormat, format.dataType, pixels); glTexSubImage1D(GL_TEXTURE_1D, level, rect.x, rect.width, format.dataFormat, format.dataType, mirrored);
break; break;
case nzImageType_2D: case nzImageType_2D:
glTexSubImage2D(GL_TEXTURE_2D, level, rect.x, rect.y, rect.width, rect.height, format.dataFormat, format.dataType, pixels); glTexSubImage2D(GL_TEXTURE_2D, level, rect.x, rect.y, rect.width, rect.height, format.dataFormat, format.dataType, mirrored);
break; break;
case nzImageType_3D: case nzImageType_3D:
glTexSubImage3D(GL_TEXTURE_3D, level, rect.x, rect.y, z, rect.width, rect.height, 1, format.dataFormat, format.dataType, pixels); glTexSubImage3D(GL_TEXTURE_3D, level, rect.x, rect.y, z, rect.width, rect.height, 1, format.dataFormat, format.dataType, mirrored);
break; break;
default: default:
@ -1185,6 +1186,8 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int
UnlockTexture(m_impl); UnlockTexture(m_impl);
delete[] mirrored;
return true; return true;
} }
/* /*
@ -1237,20 +1240,38 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 leve
return false; return false;
} }
nzUInt8 bpp = NzPixelFormat::GetBPP(m_impl->format);
// Inversion de la texture pour le repère d'OpenGL
///FIXME: Gérer l'inversion dans NzImage, et gérer également les images compressées
unsigned int faceSize = cube.width*cube.height*bpp;
unsigned int size = faceSize*cube.depth;
nzUInt8* mirrored = new nzUInt8[size];
std::memcpy(mirrored, pixels, size);
nzUInt8* ptr = mirrored;
for (unsigned int d = 0; d < cube.depth; ++d)
{
for (unsigned int j = 0; j < cube.height/2; ++j)
std::swap_ranges(&ptr[j*cube.width*bpp], &ptr[(j+1)*cube.width*bpp-1], &ptr[(cube.height-j-1)*cube.width*bpp]);
ptr += faceSize;
}
LockTexture(m_impl); LockTexture(m_impl);
switch (m_impl->type) switch (m_impl->type)
{ {
case nzImageType_1D: case nzImageType_1D:
glTexSubImage1D(GL_TEXTURE_1D, level, cube.x, cube.width, format->dataFormat, format->dataType, pixels); glTexSubImage1D(GL_TEXTURE_1D, level, cube.x, cube.width, format->dataFormat, format->dataType, mirrored);
break; break;
case nzImageType_2D: case nzImageType_2D:
glTexSubImage1D(GL_TEXTURE_2D, level, cube.x, cube.y, cube.width, cube.height, format->dataFormat, format->dataType, pixels); glTexSubImage1D(GL_TEXTURE_2D, level, cube.x, cube.y, cube.width, cube.height, format->dataFormat, format->dataType, mirrored);
break; break;
case nzImageType_3D: case nzImageType_3D:
glTexSubImage1D(GL_TEXTURE_3D, level, cube.x, cube.y, cube.z, cube.width, cube.height, cube.depth, format->dataFormat, format->dataType, pixels); glTexSubImage1D(GL_TEXTURE_3D, level, cube.x, cube.y, cube.z, cube.width, cube.height, cube.depth, format->dataFormat, format->dataType, mirrored);
break; break;
default: default:
@ -1259,6 +1280,8 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 leve
UnlockTexture(m_impl); UnlockTexture(m_impl);
delete[] mirrored;
return true; return true;
} }
*/ */
@ -1278,7 +1301,7 @@ bool NzTexture::UpdateFace(nzCubemapFace face, const NzImage& image, nzUInt8 lev
} }
#endif #endif
return UpdateFace(face, image.GetConstPixels(level), level); return UpdateFace(face, image.GetConstPixels(level), NzRectui(0, 0, image.GetWidth(), image.GetHeight()), level);
} }
bool NzTexture::UpdateFace(nzCubemapFace face, const NzImage& image, const NzRectui& rect, nzUInt8 level) bool NzTexture::UpdateFace(nzCubemapFace face, const NzImage& image, const NzRectui& rect, nzUInt8 level)
@ -1308,40 +1331,9 @@ bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, nzUInt8 le
NazaraError("Texture must be valid"); NazaraError("Texture must be valid");
return false; return false;
} }
if (m_impl->type != nzImageType_Cubemap)
{
NazaraError("UpdateFace is designed for cubemaps, use Update instead");
return false;
}
if (!pixels)
{
NazaraError("Invalid pixel source");
return false;
}
if (level >= m_impl->levelCount)
{
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_impl->levelCount) + ')');
return false;
}
#endif #endif
OpenGLFormat format; return UpdateFace(face, pixels, NzRectui(0, 0, m_impl->width, m_impl->height), level);
if (!GetOpenGLFormat(m_impl->format, &format))
{
NazaraError("Failed to get OpenGL format");
return false;
}
LockTexture(m_impl);
glTexSubImage2D(cubemapFace[face], level, 0, 0, m_impl->width, m_impl->height, format.dataFormat, format.dataType, pixels);
UnlockTexture(m_impl);
return true;
} }
bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRectui& rect, nzUInt8 level) bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRectui& rect, nzUInt8 level)
@ -1391,12 +1383,24 @@ bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRe
return false; return false;
} }
nzUInt8 bpp = NzPixelFormat::GetBPP(m_impl->format);
// Inversion de la texture pour le repère d'OpenGL
///FIXME: Gérer l'inversion dans NzImage, et gérer également les images compressées
unsigned int size = rect.width*rect.height*bpp;
nzUInt8* mirrored = new nzUInt8[size];
std::memcpy(mirrored, pixels, size);
for (unsigned int j = 0; j < rect.height/2; ++j)
std::swap_ranges(&mirrored[j*rect.width*bpp], &mirrored[(j+1)*rect.width*bpp-1], &mirrored[(rect.height-j-1)*rect.width*bpp]);
LockTexture(m_impl); LockTexture(m_impl);
glTexSubImage2D(cubemapFace[face], level, rect.x, rect.y, rect.width, rect.height, format.dataFormat, format.dataType, pixels); glTexSubImage2D(cubemapFace[face], level, rect.x, rect.y, rect.width, rect.height, format.dataFormat, format.dataType, mirrored);
UnlockTexture(m_impl); UnlockTexture(m_impl);
delete[] mirrored;
return true; return true;
} }

View File

@ -729,8 +729,7 @@ bool NzImage::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z
EnsureOwnership(); EnsureOwnership();
nzUInt8 bpp = NzPixelFormat::GetBPP(m_sharedImage->format); nzUInt8 bpp = NzPixelFormat::GetBPP(m_sharedImage->format);
nzUInt8* dstPixels = &m_sharedImage->pixels[level][(m_sharedImage->height*(m_sharedImage->width*z + rect.y) + rect.x) * bpp];
nzUInt8* dstPixels = &m_sharedImage->pixels[level][(m_sharedImage->height*(m_sharedImage->width*z + rect.y) + rect.x) * NzPixelFormat::GetBPP(m_sharedImage->format)];
unsigned int srcStride = rect.width * bpp; unsigned int srcStride = rect.width * bpp;
unsigned int blockSize = m_sharedImage->width * bpp; unsigned int blockSize = m_sharedImage->width * bpp;
for (unsigned int i = 0; i < rect.height; ++i) for (unsigned int i = 0; i < rect.height; ++i)
@ -822,8 +821,7 @@ bool NzImage::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRect
EnsureOwnership(); EnsureOwnership();
nzUInt8 bpp = NzPixelFormat::GetBPP(m_sharedImage->format); nzUInt8 bpp = NzPixelFormat::GetBPP(m_sharedImage->format);
nzUInt8* dstPixels = &m_sharedImage->pixels[level][(m_sharedImage->height*(m_sharedImage->width*(face-nzCubemapFace_PositiveX) + rect.y) + rect.x) * bpp];
nzUInt8* dstPixels = &m_sharedImage->pixels[level][(m_sharedImage->height*(m_sharedImage->width*(face-nzCubemapFace_PositiveX) + rect.y) + rect.x) * NzPixelFormat::GetBPP(m_sharedImage->format)];
unsigned int srcStride = rect.width * bpp; unsigned int srcStride = rect.width * bpp;
unsigned int blockSize = m_sharedImage->width * bpp; unsigned int blockSize = m_sharedImage->width * bpp;
for (unsigned int i = 0; i < rect.height; ++i) for (unsigned int i = 0; i < rect.height; ++i)

View File

@ -202,11 +202,11 @@ NzVector2i NzWindowImpl::GetPosition() const
return NzVector2i(rect.left, rect.top); return NzVector2i(rect.left, rect.top);
} }
NzVector2i NzWindowImpl::GetSize() const NzVector2ui NzWindowImpl::GetSize() const
{ {
RECT rect; RECT rect;
GetClientRect(m_handle, &rect); GetClientRect(m_handle, &rect);
return NzVector2i(rect.right-rect.left, rect.bottom-rect.top); return NzVector2ui(rect.right-rect.left, rect.bottom-rect.top);
} }
NzString NzWindowImpl::GetTitle() const NzString NzWindowImpl::GetTitle() const
@ -689,7 +689,7 @@ bool NzWindowImpl::HandleMessage(HWND window, UINT message, WPARAM wParam, LPARA
{ {
if (wParam != SIZE_MINIMIZED) if (wParam != SIZE_MINIMIZED)
{ {
NzVector2i size = GetSize(); // On récupère uniquement la taille de la zone client NzVector2ui size = GetSize(); // On récupère uniquement la taille de la zone client
NzEvent event; NzEvent event;
event.type = NzEvent::Resized; event.type = NzEvent::Resized;

View File

@ -45,7 +45,7 @@ class NzWindowImpl : NzNonCopyable
NzWindowHandle GetHandle() const; NzWindowHandle GetHandle() const;
unsigned int GetHeight() const; unsigned int GetHeight() const;
NzVector2i GetPosition() const; NzVector2i GetPosition() const;
NzVector2i GetSize() const; NzVector2ui GetSize() const;
NzString GetTitle() const; NzString GetTitle() const;
unsigned int GetWidth() const; unsigned int GetWidth() const;

View File

@ -222,12 +222,12 @@ NzVector2i NzWindow::GetPosition() const
return NzVector2i(0); return NzVector2i(0);
} }
NzVector2i NzWindow::GetSize() const NzVector2ui NzWindow::GetSize() const
{ {
if (m_impl) if (m_impl)
return m_impl->GetSize(); return m_impl->GetSize();
else else
return NzVector2i(0); return NzVector2ui(0U);
} }
NzString NzWindow::GetTitle() const NzString NzWindow::GetTitle() const