Merge branch 'Font-Update'
Former-commit-id: d293f78c891a74554c6b990afafdc1eb1cc0a584
This commit is contained in:
@@ -159,64 +159,64 @@ void NzDebugDrawer::Draw(const NzFrustumf& frustum)
|
||||
NzBufferMapper<NzVertexBuffer> mapper(s_vertexBuffer, nzBufferAccess_DiscardAndWrite, 0, 24);
|
||||
NzVertexStruct_XYZ* vertex = reinterpret_cast<NzVertexStruct_XYZ*>(mapper.GetPointer());
|
||||
|
||||
vertex->position.Set(frustum.GetCorner(nzCorner_NearLeftBottom));
|
||||
vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearLeftBottom));
|
||||
vertex++;
|
||||
vertex->position.Set(frustum.GetCorner(nzCorner_NearRightBottom));
|
||||
vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearRightBottom));
|
||||
vertex++;
|
||||
|
||||
vertex->position.Set(frustum.GetCorner(nzCorner_NearLeftBottom));
|
||||
vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearLeftBottom));
|
||||
vertex++;
|
||||
vertex->position.Set(frustum.GetCorner(nzCorner_NearLeftTop));
|
||||
vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearLeftTop));
|
||||
vertex++;
|
||||
|
||||
vertex->position.Set(frustum.GetCorner(nzCorner_NearLeftBottom));
|
||||
vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearLeftBottom));
|
||||
vertex++;
|
||||
vertex->position.Set(frustum.GetCorner(nzCorner_FarLeftBottom));
|
||||
vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarLeftBottom));
|
||||
vertex++;
|
||||
|
||||
vertex->position.Set(frustum.GetCorner(nzCorner_FarRightTop));
|
||||
vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarRightTop));
|
||||
vertex++;
|
||||
vertex->position.Set(frustum.GetCorner(nzCorner_FarLeftTop));
|
||||
vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarLeftTop));
|
||||
vertex++;
|
||||
|
||||
vertex->position.Set(frustum.GetCorner(nzCorner_FarRightTop));
|
||||
vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarRightTop));
|
||||
vertex++;
|
||||
vertex->position.Set(frustum.GetCorner(nzCorner_FarRightBottom));
|
||||
vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarRightBottom));
|
||||
vertex++;
|
||||
|
||||
vertex->position.Set(frustum.GetCorner(nzCorner_FarRightTop));
|
||||
vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarRightTop));
|
||||
vertex++;
|
||||
vertex->position.Set(frustum.GetCorner(nzCorner_NearRightTop));
|
||||
vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearRightTop));
|
||||
vertex++;
|
||||
|
||||
vertex->position.Set(frustum.GetCorner(nzCorner_FarLeftBottom));
|
||||
vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarLeftBottom));
|
||||
vertex++;
|
||||
vertex->position.Set(frustum.GetCorner(nzCorner_FarRightBottom));
|
||||
vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarRightBottom));
|
||||
vertex++;
|
||||
|
||||
vertex->position.Set(frustum.GetCorner(nzCorner_FarLeftBottom));
|
||||
vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarLeftBottom));
|
||||
vertex++;
|
||||
vertex->position.Set(frustum.GetCorner(nzCorner_FarLeftTop));
|
||||
vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarLeftTop));
|
||||
vertex++;
|
||||
|
||||
vertex->position.Set(frustum.GetCorner(nzCorner_NearLeftTop));
|
||||
vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearLeftTop));
|
||||
vertex++;
|
||||
vertex->position.Set(frustum.GetCorner(nzCorner_NearRightTop));
|
||||
vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearRightTop));
|
||||
vertex++;
|
||||
|
||||
vertex->position.Set(frustum.GetCorner(nzCorner_NearLeftTop));
|
||||
vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearLeftTop));
|
||||
vertex++;
|
||||
vertex->position.Set(frustum.GetCorner(nzCorner_FarLeftTop));
|
||||
vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarLeftTop));
|
||||
vertex++;
|
||||
|
||||
vertex->position.Set(frustum.GetCorner(nzCorner_NearRightBottom));
|
||||
vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearRightBottom));
|
||||
vertex++;
|
||||
vertex->position.Set(frustum.GetCorner(nzCorner_NearRightTop));
|
||||
vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearRightTop));
|
||||
vertex++;
|
||||
|
||||
vertex->position.Set(frustum.GetCorner(nzCorner_NearRightBottom));
|
||||
vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearRightBottom));
|
||||
vertex++;
|
||||
vertex->position.Set(frustum.GetCorner(nzCorner_FarRightBottom));
|
||||
vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarRightBottom));
|
||||
vertex++;
|
||||
|
||||
mapper.Unmap();
|
||||
@@ -241,64 +241,64 @@ void NzDebugDrawer::Draw(const NzOrientedBoxf& orientedBox)
|
||||
NzBufferMapper<NzVertexBuffer> mapper(s_vertexBuffer, nzBufferAccess_DiscardAndWrite, 0, 24);
|
||||
NzVertexStruct_XYZ* vertex = reinterpret_cast<NzVertexStruct_XYZ*>(mapper.GetPointer());
|
||||
|
||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_NearLeftBottom));
|
||||
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearLeftBottom));
|
||||
vertex++;
|
||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_NearRightBottom));
|
||||
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearRightBottom));
|
||||
vertex++;
|
||||
|
||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_NearLeftBottom));
|
||||
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearLeftBottom));
|
||||
vertex++;
|
||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_NearLeftTop));
|
||||
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearLeftTop));
|
||||
vertex++;
|
||||
|
||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_NearLeftBottom));
|
||||
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearLeftBottom));
|
||||
vertex++;
|
||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_FarLeftBottom));
|
||||
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarLeftBottom));
|
||||
vertex++;
|
||||
|
||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_FarRightTop));
|
||||
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarRightTop));
|
||||
vertex++;
|
||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_FarLeftTop));
|
||||
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarLeftTop));
|
||||
vertex++;
|
||||
|
||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_FarRightTop));
|
||||
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarRightTop));
|
||||
vertex++;
|
||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_FarRightBottom));
|
||||
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarRightBottom));
|
||||
vertex++;
|
||||
|
||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_FarRightTop));
|
||||
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarRightTop));
|
||||
vertex++;
|
||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_NearRightTop));
|
||||
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearRightTop));
|
||||
vertex++;
|
||||
|
||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_FarLeftBottom));
|
||||
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarLeftBottom));
|
||||
vertex++;
|
||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_FarRightBottom));
|
||||
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarRightBottom));
|
||||
vertex++;
|
||||
|
||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_FarLeftBottom));
|
||||
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarLeftBottom));
|
||||
vertex++;
|
||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_FarLeftTop));
|
||||
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarLeftTop));
|
||||
vertex++;
|
||||
|
||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_NearLeftTop));
|
||||
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearLeftTop));
|
||||
vertex++;
|
||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_NearRightTop));
|
||||
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearRightTop));
|
||||
vertex++;
|
||||
|
||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_NearLeftTop));
|
||||
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearLeftTop));
|
||||
vertex++;
|
||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_FarLeftTop));
|
||||
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarLeftTop));
|
||||
vertex++;
|
||||
|
||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_NearRightBottom));
|
||||
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearRightBottom));
|
||||
vertex++;
|
||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_NearRightTop));
|
||||
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearRightTop));
|
||||
vertex++;
|
||||
|
||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_NearRightBottom));
|
||||
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearRightBottom));
|
||||
vertex++;
|
||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_FarRightBottom));
|
||||
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarRightBottom));
|
||||
vertex++;
|
||||
|
||||
mapper.Unmap();
|
||||
@@ -363,6 +363,11 @@ void NzDebugDrawer::Draw(const NzSkeleton* skeleton)
|
||||
}
|
||||
}
|
||||
|
||||
void NzDebugDrawer::Draw(const NzVector3f& position, float size)
|
||||
{
|
||||
Draw(NzBoxf(position.x - size*0.5f, position.y - size*0.5f, position.z - size*0.5f, size, size, size));
|
||||
}
|
||||
|
||||
void NzDebugDrawer::DrawBinormals(const NzStaticMesh* subMesh)
|
||||
{
|
||||
if (!Initialize())
|
||||
@@ -662,7 +667,7 @@ bool NzDebugDrawer::Initialize()
|
||||
try
|
||||
{
|
||||
NzErrorFlags flags(nzErrorFlag_ThrowException, true);
|
||||
s_vertexBuffer.Reset(NzVertexDeclaration::Get(nzVertexLayout_XYZ), 65365, nzBufferStorage_Hardware, nzBufferUsage_Dynamic);
|
||||
s_vertexBuffer.Reset(NzVertexDeclaration::Get(nzVertexLayout_XYZ), 65365, nzDataStorage_Hardware, nzBufferUsage_Dynamic);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
|
||||
@@ -1463,8 +1463,42 @@ void NzOpenGL::SetViewport(const NzRecti& viewport)
|
||||
|
||||
bool NzOpenGL::TranslateFormat(nzPixelFormat pixelFormat, Format* format, FormatType type)
|
||||
{
|
||||
// Par défaut
|
||||
format->swizzle[0] = GL_RED;
|
||||
format->swizzle[1] = GL_GREEN;
|
||||
format->swizzle[2] = GL_BLUE;
|
||||
format->swizzle[3] = GL_ALPHA;
|
||||
|
||||
switch (pixelFormat)
|
||||
{
|
||||
case nzPixelFormat_A8:
|
||||
if (type == FormatType_Texture) // Format supporté uniquement par les textures
|
||||
{
|
||||
if (GetVersion() >= 300)
|
||||
{
|
||||
format->dataFormat = GL_RED;
|
||||
format->dataType = GL_UNSIGNED_BYTE;
|
||||
format->internalFormat = GL_R8;
|
||||
|
||||
// Simulation du format
|
||||
format->swizzle[0] = GL_ONE;
|
||||
format->swizzle[1] = GL_ONE;
|
||||
format->swizzle[2] = GL_ONE;
|
||||
format->swizzle[3] = GL_RED;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Le bon vieux format GL_ALPHA
|
||||
format->dataFormat = GL_ALPHA;
|
||||
format->dataType = GL_UNSIGNED_BYTE;
|
||||
format->internalFormat = GL_ALPHA;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
case nzPixelFormat_BGR8:
|
||||
format->dataFormat = GL_BGR;
|
||||
format->dataType = GL_UNSIGNED_BYTE;
|
||||
@@ -1496,8 +1530,58 @@ bool NzOpenGL::TranslateFormat(nzPixelFormat pixelFormat, Format* format, Format
|
||||
return true;
|
||||
|
||||
case nzPixelFormat_L8:
|
||||
if (type == FormatType_Texture) // Format supporté uniquement par les textures
|
||||
{
|
||||
if (GetVersion() >= 300)
|
||||
{
|
||||
format->dataFormat = GL_RED;
|
||||
format->dataType = GL_UNSIGNED_BYTE;
|
||||
format->internalFormat = GL_R8;
|
||||
|
||||
// Simulation du format
|
||||
format->swizzle[0] = GL_RED;
|
||||
format->swizzle[1] = GL_RED;
|
||||
format->swizzle[2] = GL_RED;
|
||||
format->swizzle[3] = GL_ONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
format->dataFormat = 0x1909; // GL_LUMINANCE
|
||||
format->dataType = GL_UNSIGNED_BYTE;
|
||||
format->internalFormat = 0x1909; // GL_LUMINANCE
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
case nzPixelFormat_LA8:
|
||||
return false;
|
||||
if (type == FormatType_Texture) // Format supporté uniquement par les textures
|
||||
{
|
||||
if (GetVersion() >= 300)
|
||||
{
|
||||
format->dataFormat = GL_RG;
|
||||
format->dataType = GL_UNSIGNED_BYTE;
|
||||
format->internalFormat = GL_RG8;
|
||||
|
||||
// Simulation du format
|
||||
format->swizzle[0] = GL_RED;
|
||||
format->swizzle[1] = GL_RED;
|
||||
format->swizzle[2] = GL_RED;
|
||||
format->swizzle[3] = GL_GREEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
format->dataFormat = 0x190A; // GL_LUMINANCE_ALPHA
|
||||
format->dataType = GL_UNSIGNED_BYTE;
|
||||
format->internalFormat = 0x190A; // GL_LUMINANCE_ALPHA;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
case nzPixelFormat_R8:
|
||||
format->dataFormat = GL_RED;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
#include <Nazara/Renderer/Renderer.hpp>
|
||||
#include <Nazara/Renderer/RenderBuffer.hpp>
|
||||
#include <Nazara/Utility/PixelFormat.hpp>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
@@ -92,6 +92,7 @@ namespace
|
||||
bool s_useVertexArrayObjects;
|
||||
unsigned int s_maxColorAttachments;
|
||||
unsigned int s_maxRenderTarget;
|
||||
unsigned int s_maxTextureSize;
|
||||
unsigned int s_maxTextureUnit;
|
||||
unsigned int s_maxVertexAttribs;
|
||||
|
||||
@@ -612,6 +613,11 @@ unsigned int NzRenderer::GetMaxRenderTargets()
|
||||
return s_maxRenderTarget;
|
||||
}
|
||||
|
||||
unsigned int NzRenderer::GetMaxTextureSize()
|
||||
{
|
||||
return s_maxTextureSize;
|
||||
}
|
||||
|
||||
unsigned int NzRenderer::GetMaxTextureUnits()
|
||||
{
|
||||
return s_maxTextureUnit;
|
||||
@@ -692,7 +698,10 @@ bool NzRenderer::Initialize()
|
||||
return false;
|
||||
}
|
||||
|
||||
NzBuffer::SetBufferFunction(nzBufferStorage_Hardware, [](NzBuffer* parent, nzBufferType type) -> NzAbstractBuffer* { return new NzHardwareBuffer(parent, type); } );
|
||||
NzBuffer::SetBufferFactory(nzDataStorage_Hardware, [](NzBuffer* parent, nzBufferType type) -> NzAbstractBuffer*
|
||||
{
|
||||
return new NzHardwareBuffer(parent, type);
|
||||
});
|
||||
|
||||
for (unsigned int i = 0; i <= nzMatrixType_Max; ++i)
|
||||
{
|
||||
@@ -703,19 +712,19 @@ bool NzRenderer::Initialize()
|
||||
}
|
||||
|
||||
// Récupération des capacités d'OpenGL
|
||||
s_capabilities[nzRendererCap_AnisotropicFilter] = NzOpenGL::IsSupported(nzOpenGLExtension_AnisotropicFilter);
|
||||
s_capabilities[nzRendererCap_ConditionalRendering] = NzOpenGL::IsSupported(nzOpenGLExtension_ConditionalRender);
|
||||
s_capabilities[nzRendererCap_FP64] = NzOpenGL::IsSupported(nzOpenGLExtension_FP64);
|
||||
s_capabilities[nzRendererCap_HardwareBuffer] = true; // Natif depuis OpenGL 1.5
|
||||
s_capabilities[nzRendererCap_Instancing] = NzOpenGL::IsSupported(nzOpenGLExtension_DrawInstanced) && NzOpenGL::IsSupported(nzOpenGLExtension_InstancedArray);
|
||||
s_capabilities[nzRendererCap_AnisotropicFilter] = NzOpenGL::IsSupported(nzOpenGLExtension_AnisotropicFilter);
|
||||
s_capabilities[nzRendererCap_ConditionalRendering] = NzOpenGL::IsSupported(nzOpenGLExtension_ConditionalRender);
|
||||
s_capabilities[nzRendererCap_FP64] = NzOpenGL::IsSupported(nzOpenGLExtension_FP64);
|
||||
s_capabilities[nzRendererCap_HardwareBuffer] = true; // Natif depuis OpenGL 1.5
|
||||
s_capabilities[nzRendererCap_Instancing] = NzOpenGL::IsSupported(nzOpenGLExtension_DrawInstanced) && NzOpenGL::IsSupported(nzOpenGLExtension_InstancedArray);
|
||||
s_capabilities[nzRendererCap_MultipleRenderTargets] = (glBindFragDataLocation != nullptr); // Natif depuis OpenGL 2.0 mais inutile sans glBindFragDataLocation
|
||||
s_capabilities[nzRendererCap_OcclusionQuery] = true; // Natif depuis OpenGL 1.5
|
||||
s_capabilities[nzRendererCap_PixelBufferObject] = NzOpenGL::IsSupported(nzOpenGLExtension_PixelBufferObject);
|
||||
s_capabilities[nzRendererCap_RenderTexture] = NzOpenGL::IsSupported(nzOpenGLExtension_FrameBufferObject);
|
||||
s_capabilities[nzRendererCap_Texture3D] = true; // Natif depuis OpenGL 1.2
|
||||
s_capabilities[nzRendererCap_TextureCubemap] = true; // Natif depuis OpenGL 1.3
|
||||
s_capabilities[nzRendererCap_TextureMulti] = true; // Natif depuis OpenGL 1.3
|
||||
s_capabilities[nzRendererCap_TextureNPOT] = true; // Natif depuis OpenGL 2.0
|
||||
s_capabilities[nzRendererCap_OcclusionQuery] = true; // Natif depuis OpenGL 1.5
|
||||
s_capabilities[nzRendererCap_PixelBufferObject] = NzOpenGL::IsSupported(nzOpenGLExtension_PixelBufferObject);
|
||||
s_capabilities[nzRendererCap_RenderTexture] = NzOpenGL::IsSupported(nzOpenGLExtension_FrameBufferObject);
|
||||
s_capabilities[nzRendererCap_Texture3D] = true; // Natif depuis OpenGL 1.2
|
||||
s_capabilities[nzRendererCap_TextureCubemap] = true; // Natif depuis OpenGL 1.3
|
||||
s_capabilities[nzRendererCap_TextureMulti] = true; // Natif depuis OpenGL 1.3
|
||||
s_capabilities[nzRendererCap_TextureNPOT] = true; // Natif depuis OpenGL 2.0
|
||||
|
||||
NzContext::EnsureContext();
|
||||
|
||||
@@ -759,6 +768,10 @@ bool NzRenderer::Initialize()
|
||||
else
|
||||
s_maxTextureUnit = 1;
|
||||
|
||||
GLint maxTextureSize;
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
|
||||
s_maxTextureSize = maxTextureSize;
|
||||
|
||||
GLint maxVertexAttribs;
|
||||
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
|
||||
s_maxVertexAttribs = static_cast<unsigned int>(maxVertexAttribs);
|
||||
@@ -775,7 +788,7 @@ bool NzRenderer::Initialize()
|
||||
s_updateFlags = Update_Matrices | Update_Shader | Update_VAO;
|
||||
s_vertexBuffer = nullptr;
|
||||
|
||||
s_fullscreenQuadBuffer.Reset(NzVertexDeclaration::Get(nzVertexLayout_XY), 4, nzBufferStorage_Hardware, nzBufferUsage_Static);
|
||||
s_fullscreenQuadBuffer.Reset(NzVertexDeclaration::Get(nzVertexLayout_XY), 4, nzDataStorage_Hardware, nzBufferUsage_Static);
|
||||
|
||||
float vertices[4*2] =
|
||||
{
|
||||
@@ -796,7 +809,7 @@ bool NzRenderer::Initialize()
|
||||
try
|
||||
{
|
||||
NzErrorFlags errFlags(nzErrorFlag_ThrowException, true);
|
||||
s_instanceBuffer.Reset(nullptr, NAZARA_RENDERER_INSTANCE_BUFFER_SIZE, nzBufferStorage_Hardware, nzBufferUsage_Dynamic);
|
||||
s_instanceBuffer.Reset(nullptr, NAZARA_RENDERER_INSTANCE_BUFFER_SIZE, nzDataStorage_Hardware, nzBufferUsage_Dynamic);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
@@ -1963,7 +1976,8 @@ void NzRenderer::OnTextureReleased(const NzTexture* texture)
|
||||
{
|
||||
if (unit.texture == texture)
|
||||
unit.texture = nullptr;
|
||||
// Inutile de changer le flag pour une texture désactivée
|
||||
|
||||
// Inutile de changer le flag pour une texture désactivée
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,16 +3,17 @@
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/Texture.hpp>
|
||||
#include <Nazara/Core/CallOnExit.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/ErrorFlags.hpp>
|
||||
#include <Nazara/Renderer/Context.hpp>
|
||||
#include <Nazara/Renderer/Renderer.hpp>
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
#include <Nazara/Utility/PixelFormat.hpp>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
///TODO: Virer les méthodes faisant référence aux faces et gérer ces dernières comme de simples niveaux de profondeurs (malgré OpenGL)
|
||||
|
||||
struct NzTextureImpl
|
||||
{
|
||||
GLuint id;
|
||||
@@ -28,112 +29,10 @@ struct NzTextureImpl
|
||||
|
||||
namespace
|
||||
{
|
||||
bool CreateTexture(NzTextureImpl* impl, bool proxy)
|
||||
inline unsigned int GetLevelSize(unsigned int size, nzUInt8 level)
|
||||
{
|
||||
NzOpenGL::Format openGLFormat;
|
||||
if (!NzOpenGL::TranslateFormat(impl->format, &openGLFormat, NzOpenGL::FormatType_Texture))
|
||||
{
|
||||
NazaraError("Format " + NzPixelFormat::ToString(impl->format) + " not supported by OpenGL");
|
||||
return false;
|
||||
}
|
||||
|
||||
GLenum target = (proxy) ? NzOpenGL::TextureTargetProxy[impl->type] : NzOpenGL::TextureTarget[impl->type];
|
||||
switch (impl->type)
|
||||
{
|
||||
case nzImageType_1D:
|
||||
{
|
||||
if (glTexStorage1D && !proxy) // Les drivers AMD semblent ne pas aimer glTexStorage avec un format proxy
|
||||
glTexStorage1D(target, impl->levelCount, openGLFormat.internalFormat, impl->width);
|
||||
else
|
||||
{
|
||||
unsigned int w = impl->width;
|
||||
for (nzUInt8 level = 0; level < impl->levelCount; ++level)
|
||||
{
|
||||
glTexImage1D(target, level, openGLFormat.internalFormat, w, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr);
|
||||
if (w > 1U)
|
||||
w >>= 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case nzImageType_1D_Array:
|
||||
case nzImageType_2D:
|
||||
{
|
||||
if (glTexStorage2D && !proxy)
|
||||
glTexStorage2D(target, impl->levelCount, openGLFormat.internalFormat, impl->width, impl->height);
|
||||
else
|
||||
{
|
||||
unsigned int w = impl->width;
|
||||
unsigned int h = impl->height;
|
||||
for (nzUInt8 level = 0; level < impl->levelCount; ++level)
|
||||
{
|
||||
glTexImage2D(target, level, openGLFormat.internalFormat, w, h, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr);
|
||||
if (w > 1U)
|
||||
w >>= 1;
|
||||
|
||||
if (h > 1U)
|
||||
h >>= 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case nzImageType_2D_Array:
|
||||
case nzImageType_3D:
|
||||
{
|
||||
if (glTexStorage3D && !proxy)
|
||||
glTexStorage3D(target, impl->levelCount, openGLFormat.internalFormat, impl->width, impl->height, impl->depth);
|
||||
else
|
||||
{
|
||||
unsigned int w = impl->width;
|
||||
unsigned int h = impl->height;
|
||||
unsigned int d = impl->depth;
|
||||
for (nzUInt8 level = 0; level < impl->levelCount; ++level)
|
||||
{
|
||||
glTexImage3D(target, level, openGLFormat.internalFormat, w, h, d, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr);
|
||||
if (w > 1U)
|
||||
w >>= 1;
|
||||
|
||||
if (h > 1U)
|
||||
h >>= 1;
|
||||
|
||||
if (d > 1U)
|
||||
d >>= 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case nzImageType_Cubemap:
|
||||
{
|
||||
if (glTexStorage2D && !proxy)
|
||||
glTexStorage2D(target, impl->levelCount, openGLFormat.internalFormat, impl->width, impl->height);
|
||||
else
|
||||
{
|
||||
unsigned int size = impl->width; // Les cubemaps ont une longueur et largeur identique
|
||||
for (nzUInt8 level = 0; level < impl->levelCount; ++level)
|
||||
{
|
||||
for (GLenum face : NzOpenGL::CubemapFace)
|
||||
glTexImage2D(face, level, openGLFormat.internalFormat, size, size, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr);
|
||||
|
||||
if (size > 1U)
|
||||
size >>= 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (proxy)
|
||||
{
|
||||
GLint internalFormat = 0;
|
||||
glGetTexLevelParameteriv(target, 0, GL_TEXTURE_INTERNAL_FORMAT, &internalFormat);
|
||||
if (internalFormat == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
// Contrairement à la classe Image, un appel à GetLevelSize(0, level) n'est pas possible
|
||||
return std::max(size >> level, 1U);
|
||||
}
|
||||
|
||||
inline void SetUnpackAlignement(nzUInt8 bpp)
|
||||
@@ -149,17 +48,16 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
NzTexture::NzTexture(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth, nzUInt8 levelCount)
|
||||
{
|
||||
NzErrorFlags flags(nzErrorFlag_ThrowException);
|
||||
Create(type, format, width, height, depth, levelCount);
|
||||
}
|
||||
|
||||
NzTexture::NzTexture(const NzImage& image)
|
||||
{
|
||||
NzErrorFlags flags(nzErrorFlag_ThrowException);
|
||||
LoadFromImage(image);
|
||||
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Failed to create texture");
|
||||
throw std::runtime_error("Constructor failed");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
NzTexture::~NzTexture()
|
||||
@@ -220,7 +118,7 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt
|
||||
|
||||
if (depth > 1)
|
||||
{
|
||||
NazaraError("1D textures must be 1 depth");
|
||||
NazaraError("1D textures must be 1 deep");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -229,7 +127,7 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt
|
||||
case nzImageType_2D:
|
||||
if (depth > 1)
|
||||
{
|
||||
NazaraError("2D textures must be 1 depth");
|
||||
NazaraError("2D textures must be 1 deep");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -241,7 +139,7 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt
|
||||
case nzImageType_Cubemap:
|
||||
if (depth > 1)
|
||||
{
|
||||
NazaraError("Cubemaps must be 1 depth");
|
||||
NazaraError("Cubemaps must be 1 deep");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -264,40 +162,44 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt
|
||||
levelCount = 1;
|
||||
}
|
||||
|
||||
std::unique_ptr<NzTextureImpl> impl(new NzTextureImpl);
|
||||
glGenTextures(1, &impl->id);
|
||||
m_impl = new NzTextureImpl;
|
||||
m_impl->depth = GetValidSize(depth);
|
||||
m_impl->format = format;
|
||||
m_impl->height = GetValidSize(height);
|
||||
m_impl->levelCount = levelCount;
|
||||
m_impl->type = type;
|
||||
m_impl->width = GetValidSize(width);
|
||||
|
||||
impl->depth = GetValidSize(depth);
|
||||
impl->format = format;
|
||||
impl->height = GetValidSize(height);
|
||||
impl->levelCount = levelCount;
|
||||
impl->type = type;
|
||||
impl->width = GetValidSize(width);
|
||||
glGenTextures(1, &m_impl->id);
|
||||
NzOpenGL::BindTexture(m_impl->type, m_impl->id);
|
||||
|
||||
NzOpenGL::BindTexture(impl->type, impl->id);
|
||||
|
||||
// Vérification du support par la carte graphique
|
||||
if (!CreateTexture(impl.get(), true))
|
||||
// En cas d'erreur (sortie prématurée), on détruit la texture
|
||||
NzCallOnExit onExit([this]()
|
||||
{
|
||||
NzOpenGL::DeleteTexture(m_impl->id);
|
||||
Destroy();
|
||||
});
|
||||
|
||||
// On précise le nombre de mipmaps avant la spécification de la texture
|
||||
// https://www.opengl.org/wiki/Hardware_specifics:_NVidia
|
||||
SetMipmapRange(0, m_impl->levelCount-1);
|
||||
if (m_impl->levelCount > 1U)
|
||||
EnableMipmapping(true);
|
||||
|
||||
// Vérification du support par la carte graphique (texture proxy)
|
||||
if (!CreateTexture(true))
|
||||
{
|
||||
NazaraError("Texture's parameters not supported by driver");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Création de la texture
|
||||
if (!CreateTexture(impl.get(), false))
|
||||
if (!CreateTexture(false))
|
||||
{
|
||||
NzOpenGL::DeleteTexture(m_impl->id);
|
||||
|
||||
NazaraError("Failed to create texture");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_impl = impl.release();
|
||||
|
||||
if (m_impl->levelCount > 1U)
|
||||
EnableMipmapping(true);
|
||||
onExit.Reset();
|
||||
|
||||
NotifyCreated();
|
||||
return true;
|
||||
@@ -346,29 +248,10 @@ bool NzTexture::Download(NzImage* image) const
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int width = m_impl->width;
|
||||
unsigned int height = m_impl->height;
|
||||
unsigned int depth = m_impl->depth;
|
||||
|
||||
// Téléchargement...
|
||||
NzOpenGL::BindTexture(m_impl->type, m_impl->id);
|
||||
for (nzUInt8 level = 0; level < m_impl->levelCount; ++level)
|
||||
{
|
||||
glGetTexImage(NzOpenGL::TextureTarget[m_impl->type], level, format.dataFormat, format.dataType, image->GetPixels(level));
|
||||
|
||||
if (width > 1)
|
||||
width >>= 1;
|
||||
|
||||
if (height > 1)
|
||||
height >>= 1;
|
||||
|
||||
if (depth > 1)
|
||||
depth >>= 1;
|
||||
}
|
||||
|
||||
// Inversion de la texture pour le repère d'OpenGL
|
||||
if (!image->FlipVertically())
|
||||
NazaraWarning("Failed to flip image");
|
||||
glGetTexImage(NzOpenGL::TextureTarget[m_impl->type], level, format.dataFormat, format.dataType, image->GetPixels(0, 0, 0, level));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -390,7 +273,11 @@ bool NzTexture::EnableMipmapping(bool enable)
|
||||
}
|
||||
|
||||
if (m_impl->levelCount == 1) // Transformation d'une texture sans mipmaps vers une texture avec mipmaps
|
||||
{
|
||||
///FIXME: Est-ce que cette opération est seulement possible ?
|
||||
m_impl->levelCount = NzImage::GetMaxLevel(m_impl->width, m_impl->height, m_impl->depth);
|
||||
SetMipmapRange(0, m_impl->levelCount-1);
|
||||
}
|
||||
|
||||
if (!m_impl->mipmapping && enable)
|
||||
m_impl->mipmapsUpdated = false;
|
||||
@@ -410,7 +297,7 @@ void NzTexture::EnsureMipmapsUpdate() const
|
||||
}
|
||||
}
|
||||
|
||||
nzUInt8 NzTexture::GetBytesPerPixel() const
|
||||
unsigned int NzTexture::GetDepth(nzUInt8 level) const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
@@ -420,20 +307,7 @@ nzUInt8 NzTexture::GetBytesPerPixel() const
|
||||
}
|
||||
#endif
|
||||
|
||||
return NzPixelFormat::GetBytesPerPixel(m_impl->format);
|
||||
}
|
||||
|
||||
unsigned int NzTexture::GetDepth() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Texture must be valid");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->depth;
|
||||
return GetLevelSize(m_impl->depth, level);
|
||||
}
|
||||
|
||||
nzPixelFormat NzTexture::GetFormat() const
|
||||
@@ -449,7 +323,7 @@ nzPixelFormat NzTexture::GetFormat() const
|
||||
return m_impl->format;
|
||||
}
|
||||
|
||||
unsigned int NzTexture::GetHeight() const
|
||||
unsigned int NzTexture::GetHeight(nzUInt8 level) const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
@@ -459,20 +333,103 @@ unsigned int NzTexture::GetHeight() const
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->height;
|
||||
return GetLevelSize(m_impl->height, level);
|
||||
}
|
||||
|
||||
NzVector2ui NzTexture::GetSize() const
|
||||
nzUInt8 NzTexture::GetLevelCount() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Texture must be valid");
|
||||
return NzVector2ui(0, 0);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return NzVector2ui(m_impl->width, m_impl->height);
|
||||
return m_impl->levelCount;
|
||||
}
|
||||
|
||||
nzUInt8 NzTexture::GetMaxLevel() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Texture must be valid");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return NzImage::GetMaxLevel(m_impl->type, m_impl->width, m_impl->height, m_impl->depth);
|
||||
}
|
||||
|
||||
unsigned int NzTexture::GetMemoryUsage() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Texture must be valid");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned int width = m_impl->width;
|
||||
unsigned int height = m_impl->height;
|
||||
unsigned int depth = m_impl->depth;
|
||||
|
||||
unsigned int size = 0;
|
||||
for (unsigned int i = 0; i < m_impl->levelCount; ++i)
|
||||
{
|
||||
size += width * height * depth;
|
||||
|
||||
if (width > 1)
|
||||
width >>= 1;
|
||||
|
||||
if (height > 1)
|
||||
height >>= 1;
|
||||
|
||||
if (depth > 1)
|
||||
depth >>= 1;
|
||||
}
|
||||
|
||||
if (m_impl->type == nzImageType_Cubemap)
|
||||
size *= 6;
|
||||
|
||||
return size * NzPixelFormat::GetBytesPerPixel(m_impl->format);
|
||||
}
|
||||
|
||||
unsigned int NzTexture::GetMemoryUsage(nzUInt8 level) const
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Texture must be valid");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (level >= m_impl->levelCount)
|
||||
{
|
||||
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_impl->levelCount) + ')');
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return (GetLevelSize(m_impl->width, level)) *
|
||||
(GetLevelSize(m_impl->height, level)) *
|
||||
((m_impl->type == nzImageType_Cubemap) ? 6 : GetLevelSize(m_impl->depth, level)) *
|
||||
NzPixelFormat::GetBytesPerPixel(m_impl->format);
|
||||
}
|
||||
|
||||
NzVector3ui NzTexture::GetSize(nzUInt8 level) const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Texture must be valid");
|
||||
return NzVector3ui(0, 0, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
return NzVector3ui(GetLevelSize(m_impl->width, level), GetLevelSize(m_impl->height, level), GetLevelSize(m_impl->depth, level));
|
||||
}
|
||||
|
||||
nzImageType NzTexture::GetType() const
|
||||
@@ -488,7 +445,7 @@ nzImageType NzTexture::GetType() const
|
||||
return m_impl->type;
|
||||
}
|
||||
|
||||
unsigned int NzTexture::GetWidth() const
|
||||
unsigned int NzTexture::GetWidth(nzUInt8 level) const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
@@ -498,7 +455,7 @@ unsigned int NzTexture::GetWidth() const
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->width;
|
||||
return GetLevelSize(m_impl->width, level);
|
||||
}
|
||||
|
||||
bool NzTexture::HasMipmaps() const
|
||||
@@ -514,30 +471,17 @@ bool NzTexture::HasMipmaps() const
|
||||
return m_impl->levelCount > 1;
|
||||
}
|
||||
|
||||
bool NzTexture::IsCompressed() const
|
||||
void NzTexture::InvalidateMipmaps()
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Texture must be valid");
|
||||
return false;
|
||||
NazaraInternalError("Texture must be valid");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
return NzPixelFormat::IsCompressed(m_impl->format);
|
||||
}
|
||||
|
||||
bool NzTexture::IsCubemap() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Texture must be valid");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->type == nzImageType_Cubemap;
|
||||
m_impl->mipmapsUpdated = false;
|
||||
}
|
||||
|
||||
bool NzTexture::IsValid() const
|
||||
@@ -573,6 +517,7 @@ bool NzTexture::LoadFromImage(const NzImage& image, bool generateMipmaps)
|
||||
nzPixelFormat format = newImage.GetFormat();
|
||||
if (!IsFormatSupported(format))
|
||||
{
|
||||
///TODO: Sélectionner le format le plus adapté selon les composantes présentes dans le premier format
|
||||
nzPixelFormat newFormat = (NzPixelFormat::HasAlpha(format)) ? nzPixelFormat_BGRA8 : nzPixelFormat_BGR8;
|
||||
NazaraWarning("Format " + NzPixelFormat::ToString(format) + " not supported, trying to convert it to " + NzPixelFormat::ToString(newFormat) + "...");
|
||||
|
||||
@@ -604,17 +549,20 @@ bool NzTexture::LoadFromImage(const NzImage& image, bool generateMipmaps)
|
||||
return false;
|
||||
}
|
||||
|
||||
NzCallOnExit destroyOnExit([this]()
|
||||
{
|
||||
Destroy();
|
||||
});
|
||||
|
||||
if (type == nzImageType_Cubemap)
|
||||
{
|
||||
for (nzUInt8 level = 0; level < levelCount; ++level)
|
||||
{
|
||||
for (unsigned int i = 0; i <= nzCubemapFace_Max; ++i)
|
||||
{
|
||||
if (!UpdateFace(static_cast<nzCubemapFace>(i), newImage.GetConstPixels(0, 0, i, level), level))
|
||||
if (!Update(newImage.GetConstPixels(0, 0, i, level), NzRectui(0, 0, newImage.GetWidth(level), newImage.GetHeight(level)), i, level))
|
||||
{
|
||||
NazaraError("Failed to update texture");
|
||||
Destroy();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -627,13 +575,13 @@ bool NzTexture::LoadFromImage(const NzImage& image, bool generateMipmaps)
|
||||
if (!Update(newImage.GetConstPixels(0, 0, 0, level), level))
|
||||
{
|
||||
NazaraError("Failed to update texture");
|
||||
Destroy();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
destroyOnExit.Reset();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -793,7 +741,7 @@ bool NzTexture::LoadFaceFromFile(nzCubemapFace face, const NzString& filePath, c
|
||||
return false;
|
||||
}
|
||||
|
||||
return UpdateFace(face, image);
|
||||
return Update(image, NzRectui(0, 0, faceSize, faceSize), face);
|
||||
}
|
||||
|
||||
bool NzTexture::LoadFaceFromMemory(nzCubemapFace face, const void* data, std::size_t size, const NzImageParams& params)
|
||||
@@ -832,7 +780,7 @@ bool NzTexture::LoadFaceFromMemory(nzCubemapFace face, const void* data, std::si
|
||||
return false;
|
||||
}
|
||||
|
||||
return UpdateFace(face, image);
|
||||
return Update(image, NzRectui(0, 0, faceSize, faceSize), face);
|
||||
}
|
||||
|
||||
bool NzTexture::LoadFaceFromStream(nzCubemapFace face, NzInputStream& stream, const NzImageParams& params)
|
||||
@@ -872,7 +820,7 @@ bool NzTexture::LoadFaceFromStream(nzCubemapFace face, NzInputStream& stream, co
|
||||
return false;
|
||||
}
|
||||
|
||||
return UpdateFace(face, image);
|
||||
return Update(image, NzRectui(0, 0, faceSize, faceSize), face);
|
||||
}
|
||||
|
||||
bool NzTexture::SetMipmapRange(nzUInt8 minLevel, nzUInt8 maxLevel)
|
||||
@@ -992,7 +940,7 @@ bool NzTexture::Update(const nzUInt8* pixels, unsigned int srcWidth, unsigned in
|
||||
}
|
||||
#endif
|
||||
|
||||
return Update(pixels, NzBoxui(std::max(m_impl->width >> level, 1U), std::max(m_impl->height >> level, 1U), std::max(m_impl->depth >> level, 1U)), srcWidth, srcHeight, level);
|
||||
return Update(pixels, NzBoxui(GetLevelSize(m_impl->width, level), GetLevelSize(m_impl->height, level), GetLevelSize(m_impl->depth, level)), srcWidth, srcHeight, level);
|
||||
}
|
||||
|
||||
bool NzTexture::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level)
|
||||
@@ -1004,12 +952,6 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int s
|
||||
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");
|
||||
@@ -1023,12 +965,13 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int s
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned int height = std::max(m_impl->height >> level, 1U);
|
||||
unsigned int height = GetLevelSize(m_impl->height, level);
|
||||
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (box.x+box.width > std::max(m_impl->width >> level, 1U) ||
|
||||
box.y+box.height > height ||
|
||||
box.z+box.depth > std::max(m_impl->depth >> level, 1U))
|
||||
unsigned int width = GetLevelSize(m_impl->width, level);
|
||||
unsigned int depth = (m_impl->type == nzImageType_Cubemap) ? 6 : GetLevelSize(m_impl->depth, level);
|
||||
if (box.x+box.width > width || box.y+box.height > height || box.z+box.depth > depth ||
|
||||
(m_impl->type == nzImageType_Cubemap && box.depth > 1)) // Nous n'autorisons pas de modifier plus d'une face du cubemap à la fois
|
||||
{
|
||||
NazaraError("Cube dimensions are out of bounds");
|
||||
return false;
|
||||
@@ -1061,16 +1004,16 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int s
|
||||
|
||||
case nzImageType_1D_Array:
|
||||
case nzImageType_2D:
|
||||
glTexSubImage2D(NzOpenGL::TextureTarget[m_impl->type], level, box.x, height-box.height-box.y, box.width, box.height, format.dataFormat, format.dataType, pixels);
|
||||
glTexSubImage2D(NzOpenGL::TextureTarget[m_impl->type], level, box.x, box.y, box.width, box.height, format.dataFormat, format.dataType, pixels);
|
||||
break;
|
||||
|
||||
case nzImageType_2D_Array:
|
||||
case nzImageType_3D:
|
||||
glTexSubImage3D(NzOpenGL::TextureTarget[m_impl->type], level, box.x, height-box.height-box.y, box.z, box.width, box.height, box.depth, format.dataFormat, format.dataType, pixels);
|
||||
glTexSubImage3D(NzOpenGL::TextureTarget[m_impl->type], level, box.x, box.y, box.z, box.width, box.height, box.depth, format.dataFormat, format.dataType, pixels);
|
||||
break;
|
||||
|
||||
case nzImageType_Cubemap:
|
||||
NazaraError("Update used on a cubemap texture, please enable safe mode");
|
||||
glTexSubImage2D(NzOpenGL::CubemapFace[box.z], level, box.x, box.y, box.width, box.height, format.dataFormat, format.dataType, pixels);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1082,118 +1025,6 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int
|
||||
return Update(pixels, NzBoxui(rect.x, rect.y, z, rect.width, rect.height, 1), srcWidth, srcHeight, level);
|
||||
}
|
||||
|
||||
bool NzTexture::UpdateFace(nzCubemapFace face, const NzImage& image, nzUInt8 level)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!image.IsValid())
|
||||
{
|
||||
NazaraError("Image must be valid");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (image.GetFormat() != m_impl->format)
|
||||
{
|
||||
NazaraError("Image format does not match texture format");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return UpdateFace(face, image.GetConstPixels(0, 0, 0, level), NzRectui(0, 0, image.GetWidth(level), image.GetHeight(level)), 0, 0, level);
|
||||
}
|
||||
|
||||
bool NzTexture::UpdateFace(nzCubemapFace face, const NzImage& image, const NzRectui& rect, nzUInt8 level)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!image.IsValid())
|
||||
{
|
||||
NazaraError("Image must be valid");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (image.GetFormat() != m_impl->format)
|
||||
{
|
||||
NazaraError("Image format does not match texture format");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return UpdateFace(face, image.GetConstPixels(0, 0, 0, level), rect, image.GetWidth(level), image.GetHeight(level), level);
|
||||
}
|
||||
|
||||
bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Texture must be valid");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return UpdateFace(face, pixels, NzRectui(0, 0, m_impl->width, m_impl->height), srcWidth, srcHeight, level);
|
||||
}
|
||||
|
||||
bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRectui& rect, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Texture must be valid");
|
||||
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 (!rect.IsValid())
|
||||
{
|
||||
NazaraError("Invalid rectangle");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned int height = std::max(m_impl->height >> level, 1U);
|
||||
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (rect.x+rect.width > std::max(m_impl->width >> level, 1U) || rect.y+rect.height > height)
|
||||
{
|
||||
NazaraError("Rectangle dimensions are out of bounds");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (level >= m_impl->levelCount)
|
||||
{
|
||||
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_impl->levelCount) + ')');
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
NzOpenGL::Format format;
|
||||
if (!NzOpenGL::TranslateFormat(m_impl->format, &format, NzOpenGL::FormatType_Texture))
|
||||
{
|
||||
NazaraError("Failed to get OpenGL format");
|
||||
return false;
|
||||
}
|
||||
|
||||
SetUnpackAlignement(NzPixelFormat::GetBytesPerPixel(m_impl->format));
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, srcWidth);
|
||||
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, srcHeight);
|
||||
|
||||
NzOpenGL::BindTexture(m_impl->type, m_impl->id);
|
||||
glTexSubImage2D(NzOpenGL::CubemapFace[face], level, rect.x, height-rect.height-rect.y, rect.width, rect.height, format.dataFormat, format.dataType, pixels);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int NzTexture::GetOpenGLID() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
@@ -1226,8 +1057,11 @@ bool NzTexture::IsFormatSupported(nzPixelFormat format)
|
||||
switch (format)
|
||||
{
|
||||
// Formats de base
|
||||
case nzPixelFormat_A8:
|
||||
case nzPixelFormat_BGR8:
|
||||
case nzPixelFormat_BGRA8:
|
||||
case nzPixelFormat_L8:
|
||||
case nzPixelFormat_LA8:
|
||||
case nzPixelFormat_RGB8:
|
||||
case nzPixelFormat_RGBA8:
|
||||
return true;
|
||||
@@ -1286,12 +1120,7 @@ bool NzTexture::IsFormatSupported(nzPixelFormat format)
|
||||
case nzPixelFormat_Stencil16:
|
||||
return false;
|
||||
|
||||
// Dépréciés depuis OpenGL 3
|
||||
///FIXME: Il doit bien exister des remplaçants (GL_RED ?)
|
||||
case nzPixelFormat_L8:
|
||||
case nzPixelFormat_LA8:
|
||||
return false;
|
||||
|
||||
// Formats compressés
|
||||
case nzPixelFormat_DXT1:
|
||||
case nzPixelFormat_DXT3:
|
||||
case nzPixelFormat_DXT5:
|
||||
@@ -1302,7 +1131,6 @@ bool NzTexture::IsFormatSupported(nzPixelFormat format)
|
||||
}
|
||||
|
||||
NazaraError("Invalid pixel format");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1330,15 +1158,119 @@ bool NzTexture::IsTypeSupported(nzImageType type)
|
||||
return false;
|
||||
}
|
||||
|
||||
void NzTexture::InvalidateMipmaps()
|
||||
bool NzTexture::CreateTexture(bool proxy)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
NzOpenGL::Format openGLFormat;
|
||||
if (!NzOpenGL::TranslateFormat(m_impl->format, &openGLFormat, NzOpenGL::FormatType_Texture))
|
||||
{
|
||||
NazaraInternalError("Texture must be valid");
|
||||
return;
|
||||
NazaraError("Format " + NzPixelFormat::ToString(m_impl->format) + " not supported by OpenGL");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_impl->mipmapsUpdated = false;
|
||||
GLenum target = (proxy) ? NzOpenGL::TextureTargetProxy[m_impl->type] : NzOpenGL::TextureTarget[m_impl->type];
|
||||
switch (m_impl->type)
|
||||
{
|
||||
case nzImageType_1D:
|
||||
{
|
||||
if (glTexStorage1D && !proxy) // Les drivers AMD semblent ne pas aimer glTexStorage avec un format proxy
|
||||
glTexStorage1D(target, m_impl->levelCount, openGLFormat.internalFormat, m_impl->width);
|
||||
else
|
||||
{
|
||||
unsigned int w = m_impl->width;
|
||||
for (nzUInt8 level = 0; level < m_impl->levelCount; ++level)
|
||||
{
|
||||
glTexImage1D(target, level, openGLFormat.internalFormat, w, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr);
|
||||
if (w > 1U)
|
||||
w >>= 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case nzImageType_1D_Array:
|
||||
case nzImageType_2D:
|
||||
{
|
||||
if (glTexStorage2D && !proxy)
|
||||
glTexStorage2D(target, m_impl->levelCount, openGLFormat.internalFormat, m_impl->width, m_impl->height);
|
||||
else
|
||||
{
|
||||
unsigned int w = m_impl->width;
|
||||
unsigned int h = m_impl->height;
|
||||
for (nzUInt8 level = 0; level < m_impl->levelCount; ++level)
|
||||
{
|
||||
glTexImage2D(target, level, openGLFormat.internalFormat, w, h, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr);
|
||||
if (w > 1U)
|
||||
w >>= 1;
|
||||
|
||||
if (h > 1U)
|
||||
h >>= 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case nzImageType_2D_Array:
|
||||
case nzImageType_3D:
|
||||
{
|
||||
if (glTexStorage3D && !proxy)
|
||||
glTexStorage3D(target, m_impl->levelCount, openGLFormat.internalFormat, m_impl->width, m_impl->height, m_impl->depth);
|
||||
else
|
||||
{
|
||||
unsigned int w = m_impl->width;
|
||||
unsigned int h = m_impl->height;
|
||||
unsigned int d = m_impl->depth;
|
||||
for (nzUInt8 level = 0; level < m_impl->levelCount; ++level)
|
||||
{
|
||||
glTexImage3D(target, level, openGLFormat.internalFormat, w, h, d, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr);
|
||||
if (w > 1U)
|
||||
w >>= 1;
|
||||
|
||||
if (h > 1U)
|
||||
h >>= 1;
|
||||
|
||||
if (d > 1U)
|
||||
d >>= 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case nzImageType_Cubemap:
|
||||
{
|
||||
if (glTexStorage2D && !proxy)
|
||||
glTexStorage2D(target, m_impl->levelCount, openGLFormat.internalFormat, m_impl->width, m_impl->height);
|
||||
else
|
||||
{
|
||||
unsigned int size = m_impl->width; // Les cubemaps ont une longueur et largeur identique
|
||||
for (nzUInt8 level = 0; level < m_impl->levelCount; ++level)
|
||||
{
|
||||
for (GLenum face : NzOpenGL::CubemapFace)
|
||||
glTexImage2D(face, level, openGLFormat.internalFormat, size, size, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr);
|
||||
|
||||
if (size > 1U)
|
||||
size >>= 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (proxy)
|
||||
{
|
||||
GLint internalFormat = 0;
|
||||
glGetTexLevelParameteriv(target, 0, GL_TEXTURE_INTERNAL_FORMAT, &internalFormat);
|
||||
if (internalFormat == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Application du swizzle
|
||||
if (!proxy && NzOpenGL::GetVersion() >= 300)
|
||||
{
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, openGLFormat.swizzle[0]);
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_G, openGLFormat.swizzle[1]);
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, openGLFormat.swizzle[2]);
|
||||
glTexParameteri(target, GL_TEXTURE_SWIZZLE_A, openGLFormat.swizzle[3]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user