Reworked Image/Texture
Improved performances Fixed some bugs It is now possible to use non-contiguous buffer Former-commit-id: 0fa7d13a740f62dae511a1549b267e2f2011d5a6
This commit is contained in:
parent
67e409ff53
commit
aa6d4c5b52
|
|
@ -66,13 +66,13 @@ class NAZARA_API NzTexture : public NzResource, NzNonCopyable
|
||||||
bool Update(const NzImage& image, nzUInt8 level = 0);
|
bool Update(const NzImage& image, nzUInt8 level = 0);
|
||||||
bool Update(const NzImage& image, const NzRectui& rect, unsigned int z = 0, nzUInt8 level = 0);
|
bool Update(const NzImage& image, const NzRectui& rect, unsigned int z = 0, nzUInt8 level = 0);
|
||||||
bool Update(const NzImage& image, const NzCubeui& cube, nzUInt8 level = 0);
|
bool Update(const NzImage& image, const NzCubeui& cube, nzUInt8 level = 0);
|
||||||
bool Update(const nzUInt8* pixels, nzUInt8 level = 0);
|
bool Update(const nzUInt8* pixels, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0);
|
||||||
bool Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z = 0, nzUInt8 level = 0);
|
bool Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z = 0, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0);
|
||||||
bool Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 level = 0);
|
bool Update(const nzUInt8* pixels, const NzCubeui& cube, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0);
|
||||||
bool UpdateFace(nzCubemapFace face, const NzImage& image, nzUInt8 level = 0);
|
bool UpdateFace(nzCubemapFace face, const NzImage& image, nzUInt8 level = 0);
|
||||||
bool UpdateFace(nzCubemapFace face, const NzImage& image, const NzRectui& rect, nzUInt8 level = 0);
|
bool UpdateFace(nzCubemapFace face, const NzImage& image, const NzRectui& rect, nzUInt8 level = 0);
|
||||||
bool UpdateFace(nzCubemapFace face, const nzUInt8* pixels, nzUInt8 level = 0);
|
bool UpdateFace(nzCubemapFace face, const nzUInt8* pixels, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0);
|
||||||
bool UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRectui& rect, nzUInt8 level = 0);
|
bool UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRectui& rect, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0);
|
||||||
|
|
||||||
void Unlock();
|
void Unlock();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -97,13 +97,14 @@ class NAZARA_API NzImage : public NzResource
|
||||||
bool SetLevelCount(nzUInt8 levelCount);
|
bool SetLevelCount(nzUInt8 levelCount);
|
||||||
bool SetPixelColor(const NzColor& color, unsigned int x, unsigned int y = 0, unsigned int z = 0);
|
bool SetPixelColor(const NzColor& color, unsigned int x, unsigned int y = 0, unsigned int z = 0);
|
||||||
|
|
||||||
bool Update(const nzUInt8* pixels, nzUInt8 level = 0);
|
bool Update(const nzUInt8* pixels, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0);
|
||||||
bool Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z = 0, nzUInt8 level = 0);
|
bool Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z = 0, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0);
|
||||||
bool Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 level = 0);
|
bool Update(const nzUInt8* pixels, const NzCubeui& cube, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0);
|
||||||
|
|
||||||
NzImage& operator=(const NzImage& image);
|
NzImage& operator=(const NzImage& image);
|
||||||
NzImage& operator=(NzImage&& image) noexcept;
|
NzImage& operator=(NzImage&& image) noexcept;
|
||||||
|
|
||||||
|
static void Copy(nzUInt8* destination, const nzUInt8* source, nzUInt8 bpp, unsigned int width, unsigned int height, unsigned int depth = 1, unsigned int dstWidth = 0, unsigned int dstHeight = 0, unsigned int srcWidth = 0, unsigned int srcHeight = 0);
|
||||||
static nzUInt8 GetMaxLevel(unsigned int width, unsigned int height, unsigned int depth = 1);
|
static nzUInt8 GetMaxLevel(unsigned int width, unsigned int height, unsigned int depth = 1);
|
||||||
|
|
||||||
struct SharedImage
|
struct SharedImage
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include <Nazara/Core/Error.hpp>
|
#include <Nazara/Core/Error.hpp>
|
||||||
#include <Nazara/Renderer/Context.hpp>
|
#include <Nazara/Renderer/Context.hpp>
|
||||||
#include <Nazara/Renderer/Renderer.hpp>
|
#include <Nazara/Renderer/Renderer.hpp>
|
||||||
|
#include <memory>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <Nazara/Renderer/Debug.hpp>
|
#include <Nazara/Renderer/Debug.hpp>
|
||||||
|
|
||||||
|
|
@ -107,9 +108,9 @@ namespace
|
||||||
|
|
||||||
case nzImageType_Cubemap:
|
case nzImageType_Cubemap:
|
||||||
{
|
{
|
||||||
if (glTexStorage2D)
|
/*if (glTexStorage2D)
|
||||||
glTexStorage2D(target, impl->levelCount, openGLFormat.internalFormat, impl->width, impl->height);
|
glTexStorage2D(target, impl->levelCount, openGLFormat.internalFormat, impl->width, impl->height);
|
||||||
else
|
else*/
|
||||||
{
|
{
|
||||||
unsigned int size = impl->width; // Les cubemaps ont une longueur et largeur identique
|
unsigned int size = impl->width; // Les cubemaps ont une longueur et largeur identique
|
||||||
for (nzUInt8 level = 0; level < impl->levelCount; ++level)
|
for (nzUInt8 level = 0; level < impl->levelCount; ++level)
|
||||||
|
|
@ -644,14 +645,33 @@ bool NzTexture::LoadFromImage(const NzImage& image, bool generateMipmaps)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (nzUInt8 level = 0; level < levelCount; ++level)
|
if (type == nzImageType_Cubemap)
|
||||||
{
|
{
|
||||||
if (!Update(newImage.GetConstPixels(level), level))
|
for (nzUInt8 level = 0; level < levelCount; ++level)
|
||||||
{
|
{
|
||||||
NazaraError("Failed to update texture");
|
for (unsigned int i = 0; i <= nzCubemapFace_Max; ++i)
|
||||||
Destroy();
|
{
|
||||||
|
if (!UpdateFace(static_cast<nzCubemapFace>(i), newImage.GetConstPixels(0, 0, i, level), level))
|
||||||
|
{
|
||||||
|
NazaraError("Failed to update texture");
|
||||||
|
Destroy();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (nzUInt8 level = 0; level < levelCount; ++level)
|
||||||
|
{
|
||||||
|
if (!Update(newImage.GetConstPixels(0, 0, 0, level), level))
|
||||||
|
{
|
||||||
|
NazaraError("Failed to update texture");
|
||||||
|
Destroy();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -745,7 +765,14 @@ bool NzTexture::Update(const NzImage& image, nzUInt8 level)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return Update(image.GetConstPixels(level), level);
|
const nzUInt8* pixels = image.GetConstPixels(0, 0, 0, level);
|
||||||
|
if (!pixels)
|
||||||
|
{
|
||||||
|
NazaraError("Failed to access image's pixels");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Update(pixels, image.GetWidth(level), image.GetHeight(level), level);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzTexture::Update(const NzImage& image, const NzRectui& rect, unsigned int z, nzUInt8 level)
|
bool NzTexture::Update(const NzImage& image, const NzRectui& rect, unsigned int z, nzUInt8 level)
|
||||||
|
|
@ -764,20 +791,14 @@ bool NzTexture::Update(const NzImage& image, const NzRectui& rect, unsigned int
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const nzUInt8* pixels = image.GetConstPixels(level, rect.x, rect.y, z);
|
const nzUInt8* pixels = image.GetConstPixels(rect.x, rect.y, z, level);
|
||||||
if (!pixels)
|
if (!pixels)
|
||||||
{
|
{
|
||||||
NazaraError("Failed to access image's pixels");
|
NazaraError("Failed to access image's pixels");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, image.GetWidth(level));
|
return Update(pixels, rect, z, image.GetWidth(level), image.GetHeight(level), level);
|
||||||
|
|
||||||
bool success = Update(pixels, rect, z, level);
|
|
||||||
|
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzTexture::Update(const NzImage& image, const NzCubeui& cube, nzUInt8 level)
|
bool NzTexture::Update(const NzImage& image, const NzCubeui& cube, nzUInt8 level)
|
||||||
|
|
@ -796,25 +817,17 @@ bool NzTexture::Update(const NzImage& image, const NzCubeui& cube, nzUInt8 level
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const nzUInt8* pixels = image.GetConstPixels(level, cube.x, cube.y, cube.z);
|
const nzUInt8* pixels = image.GetConstPixels(cube.x, cube.y, cube.z, level);
|
||||||
if (!pixels)
|
if (!pixels)
|
||||||
{
|
{
|
||||||
NazaraError("Failed to access image's pixels");
|
NazaraError("Failed to access image's pixels");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, image.GetWidth(level));
|
return Update(pixels, cube, image.GetWidth(level), image.GetHeight(level), level);
|
||||||
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, image.GetHeight(level));
|
|
||||||
|
|
||||||
bool success = Update(pixels, cube, level);
|
|
||||||
|
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
|
||||||
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzTexture::Update(const nzUInt8* pixels, nzUInt8 level)
|
bool NzTexture::Update(const nzUInt8* pixels, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level)
|
||||||
{
|
{
|
||||||
#if NAZARA_RENDERER_SAFE
|
#if NAZARA_RENDERER_SAFE
|
||||||
if (!m_impl)
|
if (!m_impl)
|
||||||
|
|
@ -824,114 +837,15 @@ bool NzTexture::Update(const nzUInt8* pixels, nzUInt8 level)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (m_impl->type == nzImageType_3D || m_impl->type == nzImageType_2D_Array)
|
return Update(pixels, NzCubeui(0, 0, 0, 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, NzCubeui(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
|
|
||||||
return Update(pixels, NzRectui(0, 0, std::max(m_impl->width >> level, 1U), std::max(m_impl->height >> level, 1U)), 0, level);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level)
|
||||||
{
|
{
|
||||||
#if NAZARA_RENDERER_SAFE
|
return Update(pixels, NzCubeui(rect.x, rect.y, z, rect.width, rect.height, 1), srcWidth, srcHeight, level);
|
||||||
if (!m_impl)
|
|
||||||
{
|
|
||||||
NazaraError("Texture must be valid");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_impl->renderTexture)
|
|
||||||
{
|
|
||||||
NazaraError("Texture is a target, it cannot be updated");
|
|
||||||
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 (!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 (z >= std::max(m_impl->depth >> level, 1U))
|
|
||||||
{
|
|
||||||
NazaraError("Z value exceeds depth (" + NzString::Number(z) + " >= (" + NzString::Number(m_impl->depth) + ')');
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
nzUInt8 bpp = NzPixelFormat::GetBytesPerPixel(m_impl->format);
|
|
||||||
|
|
||||||
// Inversion de la texture pour le repère d'OpenGL
|
|
||||||
NzImage flipped;
|
|
||||||
flipped.Create(m_impl->type, m_impl->format, rect.width, rect.height);
|
|
||||||
flipped.Update(pixels);
|
|
||||||
|
|
||||||
if (!flipped.FlipHorizontally())
|
|
||||||
NazaraWarning("Failed to flip image");
|
|
||||||
|
|
||||||
SetUnpackAlignement(bpp);
|
|
||||||
|
|
||||||
LockTexture(m_impl);
|
|
||||||
switch (m_impl->type)
|
|
||||||
{
|
|
||||||
case nzImageType_1D:
|
|
||||||
glTexSubImage1D(GL_TEXTURE_1D, level, rect.x, rect.width, format.dataFormat, format.dataType, flipped.GetConstPixels());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case nzImageType_1D_Array:
|
|
||||||
case nzImageType_2D:
|
|
||||||
glTexSubImage2D(NzOpenGL::TextureTarget[m_impl->type], level, rect.x, height-rect.height-rect.y, rect.width, rect.height, format.dataFormat, format.dataType, flipped.GetConstPixels());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case nzImageType_2D_Array:
|
|
||||||
case nzImageType_3D:
|
|
||||||
glTexSubImage3D(NzOpenGL::TextureTarget[m_impl->type], level, rect.x, height-rect.height-rect.y, z, rect.width, rect.height, 1, format.dataFormat, format.dataType, flipped.GetConstPixels());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case nzImageType_Cubemap:
|
|
||||||
NazaraError("Update used on a cubemap texture, please enable safe mode");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
UnlockTexture(m_impl);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 level)
|
bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level)
|
||||||
{
|
{
|
||||||
#if NAZARA_RENDERER_SAFE
|
#if NAZARA_RENDERER_SAFE
|
||||||
if (!m_impl)
|
if (!m_impl)
|
||||||
|
|
@ -992,14 +906,13 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 leve
|
||||||
|
|
||||||
nzUInt8 bpp = NzPixelFormat::GetBytesPerPixel(m_impl->format);
|
nzUInt8 bpp = NzPixelFormat::GetBytesPerPixel(m_impl->format);
|
||||||
|
|
||||||
// Inversion de la texture pour le repère d'OpenGL
|
|
||||||
unsigned int size = cube.width*cube.height*cube.depth*bpp;
|
unsigned int size = cube.width*cube.height*cube.depth*bpp;
|
||||||
nzUInt8* flipped = new nzUInt8[size];
|
std::unique_ptr<nzUInt8[]> flipped(new nzUInt8[size]);
|
||||||
if (!NzPixelFormat::Flip(nzPixelFlipping_Horizontally, m_impl->format, cube.width, cube.height, cube.depth, pixels, flipped))
|
NzImage::Copy(flipped.get(), pixels, bpp, cube.width, cube.height, cube.depth, 0, 0, srcWidth, srcHeight);
|
||||||
{
|
|
||||||
|
// Inversion de la texture pour le repère d'OpenGL
|
||||||
|
if (!NzPixelFormat::Flip(nzPixelFlipping_Horizontally, m_impl->format, cube.width, cube.height, cube.depth, flipped.get(), flipped.get()))
|
||||||
NazaraWarning("Failed to flip image");
|
NazaraWarning("Failed to flip image");
|
||||||
std::memcpy(flipped, pixels, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
SetUnpackAlignement(bpp);
|
SetUnpackAlignement(bpp);
|
||||||
|
|
||||||
|
|
@ -1007,17 +920,17 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 leve
|
||||||
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, flipped);
|
glTexSubImage1D(GL_TEXTURE_1D, level, cube.x, cube.width, format.dataFormat, format.dataType, flipped.get());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nzImageType_1D_Array:
|
case nzImageType_1D_Array:
|
||||||
case nzImageType_2D:
|
case nzImageType_2D:
|
||||||
glTexSubImage2D(NzOpenGL::TextureTarget[m_impl->type], level, cube.x, height-cube.height-cube.y, cube.width, cube.height, format.dataFormat, format.dataType, flipped);
|
glTexSubImage2D(NzOpenGL::TextureTarget[m_impl->type], level, cube.x, height-cube.height-cube.y, cube.width, cube.height, format.dataFormat, format.dataType, flipped.get());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nzImageType_2D_Array:
|
case nzImageType_2D_Array:
|
||||||
case nzImageType_3D:
|
case nzImageType_3D:
|
||||||
glTexSubImage3D(NzOpenGL::TextureTarget[m_impl->type], level, cube.x, height-cube.height-cube.y, cube.z, cube.width, cube.height, cube.depth, format.dataFormat, format.dataType, flipped);
|
glTexSubImage3D(NzOpenGL::TextureTarget[m_impl->type], level, cube.x, height-cube.height-cube.y, cube.z, cube.width, cube.height, cube.depth, format.dataFormat, format.dataType, flipped.get());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nzImageType_Cubemap:
|
case nzImageType_Cubemap:
|
||||||
|
|
@ -1026,8 +939,6 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 leve
|
||||||
}
|
}
|
||||||
UnlockTexture(m_impl);
|
UnlockTexture(m_impl);
|
||||||
|
|
||||||
delete[] flipped;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1047,7 +958,7 @@ bool NzTexture::UpdateFace(nzCubemapFace face, const NzImage& image, nzUInt8 lev
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return UpdateFace(face, image.GetConstPixels(level), NzRectui(0, 0, image.GetWidth(), image.GetHeight()), level);
|
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)
|
bool NzTexture::UpdateFace(nzCubemapFace face, const NzImage& image, const NzRectui& rect, nzUInt8 level)
|
||||||
|
|
@ -1066,16 +977,10 @@ bool NzTexture::UpdateFace(nzCubemapFace face, const NzImage& image, const NzRec
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, image.GetWidth(level));
|
return UpdateFace(face, image.GetConstPixels(0, 0, 0, level), rect, image.GetWidth(level), image.GetHeight(level), level);
|
||||||
|
|
||||||
bool success = UpdateFace(face, image.GetConstPixels(level), rect, level);
|
|
||||||
|
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, nzUInt8 level)
|
bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level)
|
||||||
{
|
{
|
||||||
#if NAZARA_RENDERER_SAFE
|
#if NAZARA_RENDERER_SAFE
|
||||||
if (!m_impl)
|
if (!m_impl)
|
||||||
|
|
@ -1085,10 +990,10 @@ bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, nzUInt8 le
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return UpdateFace(face, pixels, NzRectui(0, 0, m_impl->width, m_impl->height), level);
|
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, nzUInt8 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 NAZARA_RENDERER_SAFE
|
||||||
if (!m_impl)
|
if (!m_impl)
|
||||||
|
|
@ -1149,17 +1054,16 @@ bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRe
|
||||||
|
|
||||||
// Inversion de la texture pour le repère d'OpenGL
|
// Inversion de la texture pour le repère d'OpenGL
|
||||||
unsigned int size = rect.width*rect.height*bpp;
|
unsigned int size = rect.width*rect.height*bpp;
|
||||||
nzUInt8* flipped = new nzUInt8[size];
|
std::unique_ptr<nzUInt8[]> flipped(new nzUInt8[size]);
|
||||||
if (!NzPixelFormat::Flip(nzPixelFlipping_Horizontally, m_impl->format, rect.width, rect.height, 1, pixels, flipped))
|
NzImage::Copy(flipped.get(), pixels, bpp, rect.width, rect.height, 1, 0, 0, srcWidth, srcHeight);
|
||||||
{
|
|
||||||
|
if (!NzPixelFormat::Flip(nzPixelFlipping_Horizontally, m_impl->format, rect.width, rect.height, 1, flipped.get(), flipped.get()))
|
||||||
NazaraWarning("Failed to flip image");
|
NazaraWarning("Failed to flip image");
|
||||||
std::memcpy(flipped, pixels, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
SetUnpackAlignement(bpp);
|
SetUnpackAlignement(bpp);
|
||||||
|
|
||||||
LockTexture(m_impl);
|
LockTexture(m_impl);
|
||||||
glTexSubImage2D(NzOpenGL::CubemapFace[face], level, rect.x, height-rect.height-rect.y, rect.width, rect.height, format.dataFormat, format.dataType, flipped);
|
glTexSubImage2D(NzOpenGL::CubemapFace[face], level, rect.x, height-rect.height-rect.y, rect.width, rect.height, format.dataFormat, format.dataType, flipped.get());
|
||||||
UnlockTexture(m_impl);
|
UnlockTexture(m_impl);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,12 @@
|
||||||
#include <Nazara/Core/Error.hpp>
|
#include <Nazara/Core/Error.hpp>
|
||||||
#include <Nazara/Utility/Config.hpp>
|
#include <Nazara/Utility/Config.hpp>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <memory>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <Nazara/Utility/Debug.hpp>
|
#include <Nazara/Utility/Debug.hpp>
|
||||||
|
|
||||||
|
///TODO: Rajouter des warnings (Formats compressés avec les méthodes Copy/Update, tests taille dans Copy)
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
inline unsigned int GetLevelSize(unsigned int size, nzUInt8 level)
|
inline unsigned int GetLevelSize(unsigned int size, nzUInt8 level)
|
||||||
|
|
@ -66,13 +69,13 @@ m_sharedImage(image.m_sharedImage)
|
||||||
|
|
||||||
NzImage::~NzImage()
|
NzImage::~NzImage()
|
||||||
{
|
{
|
||||||
ReleaseImage();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzImage::Convert(nzPixelFormat format)
|
bool NzImage::Convert(nzPixelFormat format)
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (!m_sharedImage)
|
if (m_sharedImage == &emptyImage)
|
||||||
{
|
{
|
||||||
NazaraError("Image must be valid");
|
NazaraError("Image must be valid");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -154,6 +157,12 @@ bool NzImage::Convert(nzPixelFormat format)
|
||||||
bool NzImage::Copy(const NzImage& source, const NzCubeui& srcCube, const NzVector3ui& dstPos)
|
bool NzImage::Copy(const NzImage& source, const NzCubeui& srcCube, const NzVector3ui& dstPos)
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
|
if (m_sharedImage == &emptyImage)
|
||||||
|
{
|
||||||
|
NazaraError("Image must be valid");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!source.IsValid())
|
if (!source.IsValid())
|
||||||
{
|
{
|
||||||
NazaraError("Source image must be valid");
|
NazaraError("Source image must be valid");
|
||||||
|
|
@ -167,49 +176,19 @@ bool NzImage::Copy(const NzImage& source, const NzCubeui& srcCube, const NzVecto
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const nzUInt8* pixels = source.GetConstPixels(0, srcCube.x, srcCube.y, srcCube.z);
|
const nzUInt8* srcPtr = source.GetConstPixels(0, srcCube.x, srcCube.y, srcCube.z);
|
||||||
if (!pixels)
|
if (!srcPtr)
|
||||||
{
|
{
|
||||||
NazaraError("Failed to access pixels");
|
NazaraError("Failed to access pixels");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Correctif temporaire : Update veut de la mémoire contigüe
|
|
||||||
Il est donc nécessaire de prendre la partie de la texture que nous voulons mettre à jour
|
|
||||||
|
|
||||||
///FIXME: Trouver une interface pour gérer ce genre de problème (Façon OpenGL?)
|
|
||||||
(Appliquer l'interface à NzTexture également)
|
|
||||||
*/
|
|
||||||
nzUInt8 bpp = NzPixelFormat::GetBytesPerPixel(m_sharedImage->format);
|
nzUInt8 bpp = NzPixelFormat::GetBytesPerPixel(m_sharedImage->format);
|
||||||
unsigned int dstLineStride = srcCube.width*bpp;
|
nzUInt8* dstPtr = GetPixelPtr(m_sharedImage->pixels[0], bpp, dstPos.x, dstPos.y, dstPos.z, m_sharedImage->width, m_sharedImage->height);
|
||||||
unsigned int dstFaceStride = dstLineStride*srcCube.height;
|
|
||||||
unsigned int srcLineStride = m_sharedImage->width*bpp;
|
|
||||||
unsigned int srcFaceStride = srcLineStride*m_sharedImage->height;
|
|
||||||
|
|
||||||
nzUInt8* cube = new nzUInt8[dstFaceStride*srcCube.depth];
|
Copy(dstPtr, srcPtr, bpp, srcCube.width, srcCube.height, srcCube.depth, m_sharedImage->width, m_sharedImage->height, source.GetWidth(), source.GetHeight());
|
||||||
nzUInt8* ptr = cube;
|
|
||||||
|
|
||||||
for (unsigned int z = 0; z < srcCube.depth; ++z)
|
return true;
|
||||||
{
|
|
||||||
nzUInt8* facePixels = ptr;
|
|
||||||
for (unsigned int y = 0; y < srcCube.height; ++y)
|
|
||||||
{
|
|
||||||
std::memcpy(facePixels, pixels, dstLineStride);
|
|
||||||
|
|
||||||
facePixels += dstLineStride;
|
|
||||||
pixels += srcLineStride;
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr += dstFaceStride;
|
|
||||||
pixels += srcFaceStride;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool success = Update(cube, NzCubeui(dstPos.x, dstPos.y, dstPos.z, srcCube.width, srcCube.height, srcCube.depth));
|
|
||||||
|
|
||||||
delete[] cube;
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzImage::Create(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth, nzUInt8 levelCount)
|
bool NzImage::Create(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth, nzUInt8 levelCount)
|
||||||
|
|
@ -344,7 +323,7 @@ void NzImage::Destroy()
|
||||||
bool NzImage::Fill(const NzColor& color)
|
bool NzImage::Fill(const NzColor& color)
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (!m_sharedImage)
|
if (m_sharedImage == &emptyImage)
|
||||||
{
|
{
|
||||||
NazaraError("Image must be valid");
|
NazaraError("Image must be valid");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -358,12 +337,10 @@ bool NzImage::Fill(const NzColor& color)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nzUInt8 bpp = NzPixelFormat::GetBytesPerPixel(m_sharedImage->format);
|
nzUInt8 bpp = NzPixelFormat::GetBytesPerPixel(m_sharedImage->format);
|
||||||
nzUInt8* colorBuffer = new nzUInt8[bpp];
|
std::unique_ptr<nzUInt8[]> colorBuffer(new nzUInt8[bpp]);
|
||||||
if (!NzPixelFormat::Convert(nzPixelFormat_RGBA8, m_sharedImage->format, &color.r, colorBuffer))
|
if (!NzPixelFormat::Convert(nzPixelFormat_RGBA8, m_sharedImage->format, &color.r, colorBuffer.get()))
|
||||||
{
|
{
|
||||||
NazaraError("Failed to convert RGBA8 to " + NzPixelFormat::ToString(m_sharedImage->format));
|
NazaraError("Failed to convert RGBA8 to " + NzPixelFormat::ToString(m_sharedImage->format));
|
||||||
delete[] colorBuffer;
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -384,7 +361,7 @@ bool NzImage::Fill(const NzColor& color)
|
||||||
|
|
||||||
while (ptr < end)
|
while (ptr < end)
|
||||||
{
|
{
|
||||||
std::memcpy(ptr, colorBuffer, bpp);
|
std::memcpy(ptr, colorBuffer.get(), bpp);
|
||||||
ptr += bpp;
|
ptr += bpp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -400,8 +377,6 @@ bool NzImage::Fill(const NzColor& color)
|
||||||
depth >>= 1;
|
depth >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] colorBuffer;
|
|
||||||
|
|
||||||
SharedImage* newImage = new SharedImage(1, m_sharedImage->type, m_sharedImage->format, m_sharedImage->levelCount, levels, m_sharedImage->width, m_sharedImage->height, m_sharedImage->depth);
|
SharedImage* newImage = new SharedImage(1, m_sharedImage->type, m_sharedImage->format, m_sharedImage->levelCount, levels, m_sharedImage->width, m_sharedImage->height, m_sharedImage->depth);
|
||||||
|
|
||||||
ReleaseImage();
|
ReleaseImage();
|
||||||
|
|
@ -413,7 +388,7 @@ bool NzImage::Fill(const NzColor& color)
|
||||||
bool NzImage::Fill(const NzColor& color, const NzRectui& rect, unsigned int z)
|
bool NzImage::Fill(const NzColor& color, const NzRectui& rect, unsigned int z)
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (!m_sharedImage)
|
if (m_sharedImage == &emptyImage)
|
||||||
{
|
{
|
||||||
NazaraError("Image must be valid");
|
NazaraError("Image must be valid");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -442,12 +417,10 @@ bool NzImage::Fill(const NzColor& color, const NzRectui& rect, unsigned int z)
|
||||||
EnsureOwnership();
|
EnsureOwnership();
|
||||||
|
|
||||||
nzUInt8 bpp = NzPixelFormat::GetBytesPerPixel(m_sharedImage->format);
|
nzUInt8 bpp = NzPixelFormat::GetBytesPerPixel(m_sharedImage->format);
|
||||||
nzUInt8* pixels = new nzUInt8[bpp];
|
std::unique_ptr<nzUInt8[]> colorBuffer(new nzUInt8[bpp]);
|
||||||
if (!NzPixelFormat::Convert(nzPixelFormat_RGBA8, m_sharedImage->format, &color.r, pixels))
|
if (!NzPixelFormat::Convert(nzPixelFormat_RGBA8, m_sharedImage->format, &color.r, colorBuffer.get()))
|
||||||
{
|
{
|
||||||
NazaraError("Failed to convert RGBA8 to " + NzPixelFormat::ToString(m_sharedImage->format));
|
NazaraError("Failed to convert RGBA8 to " + NzPixelFormat::ToString(m_sharedImage->format));
|
||||||
delete[] pixels;
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -461,22 +434,20 @@ bool NzImage::Fill(const NzColor& color, const NzRectui& rect, unsigned int z)
|
||||||
nzUInt8* end = dstPixels + srcStride;
|
nzUInt8* end = dstPixels + srcStride;
|
||||||
while (start < end)
|
while (start < end)
|
||||||
{
|
{
|
||||||
std::memcpy(start, pixels, bpp);
|
std::memcpy(start, colorBuffer.get(), bpp);
|
||||||
start += bpp;
|
start += bpp;
|
||||||
}
|
}
|
||||||
|
|
||||||
dstPixels += dstStride;
|
dstPixels += dstStride;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] pixels;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzImage::Fill(const NzColor& color, const NzCubeui& cube)
|
bool NzImage::Fill(const NzColor& color, const NzCubeui& cube)
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (!m_sharedImage)
|
if (m_sharedImage == &emptyImage)
|
||||||
{
|
{
|
||||||
NazaraError("Image must be valid");
|
NazaraError("Image must be valid");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -498,12 +469,10 @@ bool NzImage::Fill(const NzColor& color, const NzCubeui& cube)
|
||||||
EnsureOwnership();
|
EnsureOwnership();
|
||||||
|
|
||||||
nzUInt8 bpp = NzPixelFormat::GetBytesPerPixel(m_sharedImage->format);
|
nzUInt8 bpp = NzPixelFormat::GetBytesPerPixel(m_sharedImage->format);
|
||||||
nzUInt8* pixels = new nzUInt8[bpp];
|
std::unique_ptr<nzUInt8[]> colorBuffer(new nzUInt8[bpp]);
|
||||||
if (!NzPixelFormat::Convert(nzPixelFormat_RGBA8, m_sharedImage->format, &color.r, pixels))
|
if (!NzPixelFormat::Convert(nzPixelFormat_RGBA8, m_sharedImage->format, &color.r, colorBuffer.get()))
|
||||||
{
|
{
|
||||||
NazaraError("Failed to convert RGBA8 to " + NzPixelFormat::ToString(m_sharedImage->format));
|
NazaraError("Failed to convert RGBA8 to " + NzPixelFormat::ToString(m_sharedImage->format));
|
||||||
delete[] pixels;
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -521,7 +490,7 @@ bool NzImage::Fill(const NzColor& color, const NzCubeui& cube)
|
||||||
nzUInt8* end = facePixels + srcStride;
|
nzUInt8* end = facePixels + srcStride;
|
||||||
while (start < end)
|
while (start < end)
|
||||||
{
|
{
|
||||||
std::memcpy(start, pixels, bpp);
|
std::memcpy(start, colorBuffer.get(), bpp);
|
||||||
start += bpp;
|
start += bpp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -531,15 +500,13 @@ bool NzImage::Fill(const NzColor& color, const NzCubeui& cube)
|
||||||
dstPixels += faceSize;
|
dstPixels += faceSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] pixels;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzImage::FlipHorizontally()
|
bool NzImage::FlipHorizontally()
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (!m_sharedImage)
|
if (m_sharedImage == &emptyImage)
|
||||||
{
|
{
|
||||||
NazaraError("Image must be valid");
|
NazaraError("Image must be valid");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -577,7 +544,7 @@ bool NzImage::FlipHorizontally()
|
||||||
bool NzImage::FlipVertically()
|
bool NzImage::FlipVertically()
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (!m_sharedImage)
|
if (m_sharedImage == &emptyImage)
|
||||||
{
|
{
|
||||||
NazaraError("Image must be valid");
|
NazaraError("Image must be valid");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -620,31 +587,12 @@ nzUInt8 NzImage::GetBytesPerPixel() const
|
||||||
const nzUInt8* NzImage::GetConstPixels(unsigned int x, unsigned int y, unsigned int z, nzUInt8 level) const
|
const nzUInt8* NzImage::GetConstPixels(unsigned int x, unsigned int y, unsigned int z, nzUInt8 level) const
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (!m_sharedImage)
|
if (m_sharedImage == &emptyImage)
|
||||||
{
|
{
|
||||||
NazaraError("Image must be valid");
|
NazaraError("Image must be valid");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x >= m_sharedImage->width)
|
|
||||||
{
|
|
||||||
NazaraError("X value exceeds width (" + NzString::Number(x) + " >= (" + NzString::Number(m_sharedImage->width) + ')');
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (y >= m_sharedImage->height)
|
|
||||||
{
|
|
||||||
NazaraError("Y value exceeds width (" + NzString::Number(y) + " >= (" + NzString::Number(m_sharedImage->height) + ')');
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int depth = (m_sharedImage->type == nzImageType_Cubemap) ? 6 : m_sharedImage->depth;
|
|
||||||
if (z >= depth)
|
|
||||||
{
|
|
||||||
NazaraError("Z value exceeds depth (" + NzString::Number(z) + " >= (" + NzString::Number(depth) + ')');
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (level >= m_sharedImage->levelCount)
|
if (level >= m_sharedImage->levelCount)
|
||||||
{
|
{
|
||||||
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
|
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
|
||||||
|
|
@ -652,7 +600,32 @@ const nzUInt8* NzImage::GetConstPixels(unsigned int x, unsigned int y, unsigned
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return GetPixelPtr(m_sharedImage->pixels[level], NzPixelFormat::GetBytesPerPixel(m_sharedImage->format), x, y, z, m_sharedImage->width, m_sharedImage->height);
|
unsigned int width = GetLevelSize(m_sharedImage->width, level);
|
||||||
|
#if NAZARA_UTILITY_SAFE
|
||||||
|
if (x >= width)
|
||||||
|
{
|
||||||
|
NazaraError("X value exceeds width (" + NzString::Number(x) + " >= (" + NzString::Number(width) + ')');
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
unsigned int height = GetLevelSize(m_sharedImage->height, level);
|
||||||
|
#if NAZARA_UTILITY_SAFE
|
||||||
|
if (y >= height)
|
||||||
|
{
|
||||||
|
NazaraError("Y value exceeds height (" + NzString::Number(y) + " >= (" + NzString::Number(height) + ')');
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int depth = (m_sharedImage->type == nzImageType_Cubemap) ? 6 : GetLevelSize(m_sharedImage->depth, level);
|
||||||
|
if (z >= depth)
|
||||||
|
{
|
||||||
|
NazaraError("Z value exceeds depth (" + NzString::Number(z) + " >= (" + NzString::Number(depth) + ')');
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return GetPixelPtr(m_sharedImage->pixels[level], NzPixelFormat::GetBytesPerPixel(m_sharedImage->format), x, y, z, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int NzImage::GetDepth(nzUInt8 level) const
|
unsigned int NzImage::GetDepth(nzUInt8 level) const
|
||||||
|
|
@ -699,7 +672,7 @@ nzUInt8 NzImage::GetMaxLevel() const
|
||||||
NzColor NzImage::GetPixelColor(unsigned int x, unsigned int y, unsigned int z) const
|
NzColor NzImage::GetPixelColor(unsigned int x, unsigned int y, unsigned int z) const
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (!m_sharedImage)
|
if (m_sharedImage == &emptyImage)
|
||||||
{
|
{
|
||||||
NazaraError("Image must be valid");
|
NazaraError("Image must be valid");
|
||||||
return NzColor();
|
return NzColor();
|
||||||
|
|
@ -719,7 +692,7 @@ NzColor NzImage::GetPixelColor(unsigned int x, unsigned int y, unsigned int z) c
|
||||||
|
|
||||||
if (y >= m_sharedImage->height)
|
if (y >= m_sharedImage->height)
|
||||||
{
|
{
|
||||||
NazaraError("Y value exceeds width (" + NzString::Number(y) + " >= (" + NzString::Number(m_sharedImage->height) + ')');
|
NazaraError("Y value exceeds height (" + NzString::Number(y) + " >= (" + NzString::Number(m_sharedImage->height) + ')');
|
||||||
return NzColor();
|
return NzColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -743,32 +716,43 @@ NzColor NzImage::GetPixelColor(unsigned int x, unsigned int y, unsigned int z) c
|
||||||
nzUInt8* NzImage::GetPixels(unsigned int x, unsigned int y, unsigned int z, nzUInt8 level)
|
nzUInt8* NzImage::GetPixels(unsigned int x, unsigned int y, unsigned int z, nzUInt8 level)
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (!m_sharedImage)
|
if (m_sharedImage == &emptyImage)
|
||||||
{
|
{
|
||||||
NazaraError("Image must be valid");
|
NazaraError("Image must be valid");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x >= m_sharedImage->width)
|
if (level >= m_sharedImage->levelCount)
|
||||||
{
|
{
|
||||||
NazaraError("X value exceeds width (" + NzString::Number(x) + " >= (" + NzString::Number(m_sharedImage->width) + ')');
|
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
unsigned int width = GetLevelSize(m_sharedImage->width, level);
|
||||||
|
#if NAZARA_UTILITY_SAFE
|
||||||
|
if (x >= width)
|
||||||
|
{
|
||||||
|
NazaraError("X value exceeds width (" + NzString::Number(x) + " >= (" + NzString::Number(width) + ')');
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
unsigned int height = GetLevelSize(m_sharedImage->height, level);
|
||||||
|
#if NAZARA_UTILITY_SAFE
|
||||||
|
if (y >= height)
|
||||||
|
{
|
||||||
|
NazaraError("Y value exceeds height (" + NzString::Number(y) + " >= (" + NzString::Number(height) + ')');
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (y >= m_sharedImage->height)
|
unsigned int depth = (m_sharedImage->type == nzImageType_Cubemap) ? 6 : GetLevelSize(m_sharedImage->depth, level);
|
||||||
{
|
|
||||||
NazaraError("Y value exceeds width (" + NzString::Number(y) + " >= (" + NzString::Number(m_sharedImage->height) + ')');
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int depth = (m_sharedImage->type == nzImageType_Cubemap) ? 6 : m_sharedImage->depth;
|
|
||||||
if (z >= depth)
|
if (z >= depth)
|
||||||
{
|
{
|
||||||
NazaraError("Z value exceeds depth (" + NzString::Number(z) + " >= (" + NzString::Number(depth) + ')');
|
NazaraError("Z value exceeds depth (" + NzString::Number(z) + " >= (" + NzString::Number(depth) + ')');
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (level >= m_sharedImage->levelCount)
|
if (level >= m_sharedImage->levelCount)
|
||||||
{
|
{
|
||||||
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
|
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
|
||||||
|
|
@ -875,7 +859,7 @@ bool NzImage::LoadFromStream(NzInputStream& stream, const NzImageParams& params)
|
||||||
bool NzImage::SetLevelCount(nzUInt8 levelCount)
|
bool NzImage::SetLevelCount(nzUInt8 levelCount)
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (!m_sharedImage)
|
if (m_sharedImage == &emptyImage)
|
||||||
{
|
{
|
||||||
NazaraError("Image must be valid");
|
NazaraError("Image must be valid");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -920,7 +904,7 @@ bool NzImage::SetLevelCount(nzUInt8 levelCount)
|
||||||
bool NzImage::SetPixelColor(const NzColor& color, unsigned int x, unsigned int y, unsigned int z)
|
bool NzImage::SetPixelColor(const NzColor& color, unsigned int x, unsigned int y, unsigned int z)
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (!m_sharedImage)
|
if (m_sharedImage == &emptyImage)
|
||||||
{
|
{
|
||||||
NazaraError("Image must be valid");
|
NazaraError("Image must be valid");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -940,7 +924,7 @@ bool NzImage::SetPixelColor(const NzColor& color, unsigned int x, unsigned int y
|
||||||
|
|
||||||
if (y >= m_sharedImage->height)
|
if (y >= m_sharedImage->height)
|
||||||
{
|
{
|
||||||
NazaraError("Y value exceeds width (" + NzString::Number(y) + " >= (" + NzString::Number(m_sharedImage->height) + ')');
|
NazaraError("Y value exceeds height (" + NzString::Number(y) + " >= (" + NzString::Number(m_sharedImage->height) + ')');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -963,10 +947,10 @@ bool NzImage::SetPixelColor(const NzColor& color, unsigned int x, unsigned int y
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzImage::Update(const nzUInt8* pixels, nzUInt8 level)
|
bool NzImage::Update(const nzUInt8* pixels, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level)
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (!m_sharedImage)
|
if (m_sharedImage == &emptyImage)
|
||||||
{
|
{
|
||||||
NazaraError("Image must be valid");
|
NazaraError("Image must be valid");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -987,15 +971,20 @@ bool NzImage::Update(const nzUInt8* pixels, nzUInt8 level)
|
||||||
|
|
||||||
EnsureOwnership();
|
EnsureOwnership();
|
||||||
|
|
||||||
std::memcpy(m_sharedImage->pixels[level], pixels, GetSize(level));
|
Copy(m_sharedImage->pixels[level], pixels, NzPixelFormat::GetBytesPerPixel(m_sharedImage->format),
|
||||||
|
GetLevelSize(m_sharedImage->width, level),
|
||||||
|
GetLevelSize(m_sharedImage->height, level),
|
||||||
|
GetLevelSize(m_sharedImage->depth, level),
|
||||||
|
0, 0,
|
||||||
|
srcWidth, srcHeight);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzImage::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z, nzUInt8 level)
|
bool NzImage::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level)
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (!m_sharedImage)
|
if (m_sharedImage == &emptyImage)
|
||||||
{
|
{
|
||||||
NazaraError("Image must be valid");
|
NazaraError("Image must be valid");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1007,17 +996,17 @@ bool NzImage::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (level >= m_sharedImage->levelCount)
|
|
||||||
{
|
|
||||||
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rect.IsValid())
|
if (!rect.IsValid())
|
||||||
{
|
{
|
||||||
NazaraError("Invalid rectangle");
|
NazaraError("Invalid rectangle");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (level >= m_sharedImage->levelCount)
|
||||||
|
{
|
||||||
|
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
unsigned int width = GetLevelSize(m_sharedImage->width, level);
|
unsigned int width = GetLevelSize(m_sharedImage->width, level);
|
||||||
|
|
@ -1042,23 +1031,19 @@ bool NzImage::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z
|
||||||
|
|
||||||
nzUInt8 bpp = NzPixelFormat::GetBytesPerPixel(m_sharedImage->format);
|
nzUInt8 bpp = NzPixelFormat::GetBytesPerPixel(m_sharedImage->format);
|
||||||
nzUInt8* dstPixels = GetPixelPtr(m_sharedImage->pixels[level], bpp, rect.x, rect.y, z, width, height);
|
nzUInt8* dstPixels = GetPixelPtr(m_sharedImage->pixels[level], bpp, rect.x, rect.y, z, width, height);
|
||||||
unsigned int srcStride = rect.width * bpp;
|
|
||||||
unsigned int dstStride = m_sharedImage->width * bpp;
|
Copy(dstPixels, pixels, bpp,
|
||||||
for (unsigned int y = 0; y < rect.height; ++y)
|
rect.width, rect.height, 1,
|
||||||
{
|
width, height,
|
||||||
std::memcpy(dstPixels, pixels, srcStride);
|
srcWidth, srcHeight);
|
||||||
pixels += srcStride;
|
|
||||||
dstPixels += dstStride;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzImage::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 level)
|
bool NzImage::Update(const nzUInt8* pixels, const NzCubeui& cube, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level)
|
||||||
{
|
{
|
||||||
///FIXME: Vérifier que ça fonctionne correctement
|
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (!m_sharedImage)
|
if (m_sharedImage == &emptyImage)
|
||||||
{
|
{
|
||||||
NazaraError("Image must be valid");
|
NazaraError("Image must be valid");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1079,7 +1064,6 @@ bool NzImage::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 level)
|
||||||
|
|
||||||
unsigned int width = GetLevelSize(m_sharedImage->width, level);
|
unsigned int width = GetLevelSize(m_sharedImage->width, level);
|
||||||
unsigned int height = GetLevelSize(m_sharedImage->height, level);
|
unsigned int height = GetLevelSize(m_sharedImage->height, level);
|
||||||
unsigned int depth = (m_sharedImage->type == nzImageType_Cubemap) ? 6 : GetLevelSize(m_sharedImage->height, level);
|
|
||||||
|
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (!cube.IsValid())
|
if (!cube.IsValid())
|
||||||
|
|
@ -1088,7 +1072,8 @@ bool NzImage::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 level)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cube.x+cube.width > width || cube.y+cube.height > height || cube.z+cube.depth > depth)
|
// Nous n'autorisons pas de modifier plus d'une face du cubemap à la fois
|
||||||
|
if (cube.x+cube.width > width || cube.y+cube.height > height || cube.z+cube.depth > GetLevelSize(m_sharedImage->height, level))
|
||||||
{
|
{
|
||||||
NazaraError("Cube dimensions are out of bounds");
|
NazaraError("Cube dimensions are out of bounds");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1099,21 +1084,11 @@ bool NzImage::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 level)
|
||||||
|
|
||||||
nzUInt8 bpp = NzPixelFormat::GetBytesPerPixel(m_sharedImage->format);
|
nzUInt8 bpp = NzPixelFormat::GetBytesPerPixel(m_sharedImage->format);
|
||||||
nzUInt8* dstPixels = GetPixelPtr(m_sharedImage->pixels[level], bpp, cube.x, cube.y, cube.z, width, height);
|
nzUInt8* dstPixels = GetPixelPtr(m_sharedImage->pixels[level], bpp, cube.x, cube.y, cube.z, width, height);
|
||||||
unsigned int srcStride = cube.width * bpp;
|
|
||||||
unsigned int dstStride = width * bpp;
|
|
||||||
unsigned int faceSize = dstStride * height;
|
|
||||||
for (unsigned int z = 0; z < cube.depth; ++z)
|
|
||||||
{
|
|
||||||
nzUInt8* facePixels = dstPixels;
|
|
||||||
for (unsigned int y = 0; y < cube.height; ++y)
|
|
||||||
{
|
|
||||||
std::memcpy(facePixels, pixels, srcStride);
|
|
||||||
pixels += srcStride;
|
|
||||||
facePixels += dstStride;
|
|
||||||
}
|
|
||||||
|
|
||||||
dstPixels += faceSize;
|
Copy(dstPixels, pixels, bpp,
|
||||||
}
|
cube.width, cube.height, cube.depth,
|
||||||
|
width, height,
|
||||||
|
srcWidth, srcHeight);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -1140,13 +1115,55 @@ NzImage& NzImage::operator=(NzImage&& image) noexcept
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NzImage::Copy(nzUInt8* destination, const nzUInt8* source, nzUInt8 bpp, unsigned int width, unsigned int height, unsigned int depth, unsigned int dstWidth, unsigned int dstHeight, unsigned int srcWidth, unsigned int srcHeight)
|
||||||
|
{
|
||||||
|
if (dstWidth == 0)
|
||||||
|
dstWidth = width;
|
||||||
|
|
||||||
|
if (dstHeight == 0)
|
||||||
|
dstHeight = height;
|
||||||
|
|
||||||
|
if (srcWidth == 0)
|
||||||
|
srcWidth = width;
|
||||||
|
|
||||||
|
if (srcHeight == 0)
|
||||||
|
srcHeight = height;
|
||||||
|
|
||||||
|
if ((height == 1 || (dstWidth == width && srcWidth == width)) && (depth == 1 || (dstHeight == height && srcHeight == height)))
|
||||||
|
std::memcpy(destination, source, width*height*depth*bpp);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned int lineStride = width * bpp;
|
||||||
|
unsigned int dstLineStride = dstWidth * bpp;
|
||||||
|
unsigned int dstFaceStride = dstLineStride * dstHeight;
|
||||||
|
unsigned int srcLineStride = srcWidth * bpp;
|
||||||
|
unsigned int srcFaceStride = srcLineStride * srcHeight;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < depth; ++i)
|
||||||
|
{
|
||||||
|
nzUInt8* dstFacePtr = destination;
|
||||||
|
const nzUInt8* srcFacePtr = source;
|
||||||
|
for (unsigned int y = 0; y < height; ++y)
|
||||||
|
{
|
||||||
|
std::memcpy(dstFacePtr, srcFacePtr, lineStride);
|
||||||
|
|
||||||
|
dstFacePtr += dstLineStride;
|
||||||
|
srcFacePtr += srcLineStride;
|
||||||
|
}
|
||||||
|
|
||||||
|
destination += dstFaceStride;
|
||||||
|
source += srcFaceStride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nzUInt8 NzImage::GetMaxLevel(unsigned int width, unsigned int height, unsigned int depth)
|
nzUInt8 NzImage::GetMaxLevel(unsigned int width, unsigned int height, unsigned int depth)
|
||||||
{
|
{
|
||||||
static const float l2 = std::log(2.f);
|
static const float invLog2 = 1.f/std::log(2.f);
|
||||||
|
|
||||||
unsigned int widthLevel = std::log(static_cast<float>(width))/l2;
|
unsigned int widthLevel = invLog2 * std::log(static_cast<float>(width));
|
||||||
unsigned int heightLevel = std::log(static_cast<float>(height))/l2;
|
unsigned int heightLevel = invLog2 * std::log(static_cast<float>(height));
|
||||||
unsigned int depthLevel = std::log(static_cast<float>(depth))/l2;
|
unsigned int depthLevel = invLog2 * std::log(static_cast<float>(depth));
|
||||||
|
|
||||||
return std::max(std::max(std::max(widthLevel, heightLevel), depthLevel), 1U);
|
return std::max(std::max(std::max(widthLevel, heightLevel), depthLevel), 1U);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue