First part of render texture commit

Added NzContext::EnsureContext and NzContext::GetThreadContext
Added NzCube
Added NzRect::GetCenter
Added methods to send vectors to shaders
Added NzRenderer::SetViewport
Fixed NzRect::ExtendTo calculations
Fixed NzImage::Update checks with level > 0
No longer use glTexStorage when creating a texture to prevent a bug
NzBuffer's Lock and Unlock operations renamed to Map and Unmap
NzVector2/3/4 can now cast implicitly to a pointer
Optimized compilation time of String.hpp
Optimized normalisaton of quaternions
Optimized passing uniforms to shaders
Quaternion now automaticaly Normalize h
Removed macro definition of NAZARA_RENDERER_OPENGL from Renderer
Removed implicit cast from NzVector2/3/4 to NzString
Renamed nzBufferLock to nzBufferAccess
Renamed NzRenderTarget::CanActivate to IsValid
This commit is contained in:
Lynix
2012-06-13 07:40:31 +02:00
parent b1632842ae
commit e2a38b3790
55 changed files with 1400 additions and 417 deletions

View File

@@ -5,6 +5,7 @@
#include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Renderer/Texture.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Renderer/Context.hpp>
#include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Renderer/RenderWindow.hpp>
#include <stdexcept>
@@ -14,8 +15,9 @@ struct NzTextureImpl
{
// GCC 4.7 !!!!!!
NzTextureImpl() :
isTarget(false),
mipmapping(false),
mipmapsUpdated(false)
mipmapsUpdated(true)
{
}
@@ -23,6 +25,7 @@ struct NzTextureImpl
nzImageType type;
nzPixelFormat format;
nzUInt8 levelCount;
bool isTarget;
bool mipmapping;
bool mipmapsUpdated;
unsigned int depth;
@@ -73,31 +76,31 @@ namespace
format->dataFormat = GL_BGR;
format->dataType = GL_UNSIGNED_BYTE;
format->internalFormat = GL_RGB8;
break;
return true;
case nzPixelFormat_BGRA8:
format->dataFormat = GL_BGRA;
format->dataType = GL_UNSIGNED_BYTE;
format->internalFormat = GL_RGBA8;
break;
return true;
case nzPixelFormat_DXT1:
format->dataFormat = GL_RGB;
format->dataType = GL_UNSIGNED_BYTE;
format->internalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
break;
return true;
case nzPixelFormat_DXT3:
format->dataFormat = GL_RGBA;
format->dataType = GL_UNSIGNED_BYTE;
format->internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
break;
return true;
case nzPixelFormat_DXT5:
format->dataFormat = GL_RGBA;
format->dataType = GL_UNSIGNED_BYTE;
format->internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
break;
return true;
case nzPixelFormat_L8:
case nzPixelFormat_LA8:
@@ -108,32 +111,35 @@ namespace
format->dataFormat = GL_RGBA;
format->dataType = GL_UNSIGNED_SHORT_5_5_5_1;
format->internalFormat = GL_RGB5_A1;
break;
return true;
case nzPixelFormat_RGB8:
format->dataFormat = GL_RGB;
format->dataType = GL_UNSIGNED_BYTE;
format->internalFormat = GL_RGB8;
break;
return true;
case nzPixelFormat_RGBA4:
format->dataFormat = GL_RGBA;
format->dataType = GL_UNSIGNED_SHORT_4_4_4_4;
format->internalFormat = GL_RGBA4;
break;
return true;
case nzPixelFormat_RGBA8:
format->dataFormat = GL_RGBA;
format->dataType = GL_UNSIGNED_BYTE;
format->internalFormat = GL_RGBA8;
break;
return true;
default:
NazaraError("Pixel format not handled");
case nzPixelFormat_Undefined:
case nzPixelFormat_Count:
NazaraInternalError("Invalid pixel format");
return false;
}
return true;
NazaraError("Pixel format not handled");
return false;
}
bool CreateTexture(NzTextureImpl* impl, bool proxy)
@@ -145,8 +151,6 @@ namespace
return false;
}
static const bool texStorageSupported = NzOpenGL::IsSupported(NzOpenGL::TextureStorage);
GLenum target;
switch (impl->type)
{
@@ -154,15 +158,16 @@ namespace
{
target = (proxy) ? GL_TEXTURE_1D : GL_PROXY_TEXTURE_1D;
if (texStorageSupported)
/*if (glTexStorage1D)
glTexStorage1D(target, impl->levelCount, openGLFormat.internalFormat, impl->width);
else
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);
w = std::max(w/2, 1U);
if (w > 1U)
w >>= 1;
}
}
break;
@@ -172,17 +177,20 @@ namespace
{
target = (proxy) ? GL_TEXTURE_2D : GL_PROXY_TEXTURE_2D;
if (texStorageSupported)
/*if (glTexStorage2D)
glTexStorage2D(target, impl->levelCount, openGLFormat.internalFormat, impl->width, impl->height);
else
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);
w = std::max(w/2, 1U);
h = std::max(h/2, 1U);
if (w > 1U)
w >>= 1;
if (h > 1U)
h >>= 1;
}
}
break;
@@ -192,9 +200,9 @@ namespace
{
target = (proxy) ? GL_TEXTURE_3D : GL_PROXY_TEXTURE_3D;
if (texStorageSupported)
/*if (glTexStorage3D)
glTexStorage3D(target, impl->levelCount, openGLFormat.internalFormat, impl->width, impl->height, impl->depth);
else
else*/
{
unsigned int w = impl->width;
unsigned int h = impl->height;
@@ -202,9 +210,14 @@ namespace
for (nzUInt8 level = 0; level < impl->levelCount; ++level)
{
glTexImage3D(target, level, openGLFormat.internalFormat, w, h, d, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr);
w = std::max(w/2, 1U);
h = std::max(h/2, 1U);
d = std::max(d/2, 1U);
if (w > 1U)
w >>= 1;
if (h > 1U)
h >>= 1;
if (d > 1U)
d >>= 1;
}
}
break;
@@ -214,9 +227,9 @@ namespace
{
target = (proxy) ? GL_TEXTURE_CUBE_MAP : GL_PROXY_TEXTURE_CUBE_MAP;
if (texStorageSupported)
/*if (glTexStorage2D)
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
for (nzUInt8 level = 0; level < impl->levelCount; ++level)
@@ -224,7 +237,8 @@ namespace
for (GLenum face : cubemapFace)
glTexImage2D(face, level, openGLFormat.internalFormat, size, size, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr);
size = std::max(size/2, 1U);
if (size > 1U)
size >>= 1;
}
}
break;
@@ -253,6 +267,8 @@ namespace
{
if (lockedLevel[impl->type]++ == 0)
{
NzContext::EnsureContext();
GLint previous;
glGetIntegerv(openglTargetBinding[impl->type], &previous);
@@ -265,6 +281,14 @@ namespace
void UnlockTexture(NzTextureImpl* impl)
{
#ifdef NAZARA_DEBUG
if (NzContext::GetCurrent() == nullptr)
{
NazaraError("No active context");
return;
}
#endif
#if NAZARA_RENDERER_SAFE
if (lockedLevel[impl->type] == 0)
{
@@ -302,7 +326,7 @@ NzTexture::~NzTexture()
Destroy();
}
bool NzTexture::Bind()
bool NzTexture::Bind() const
{
#if NAZARA_RENDERER_SAFE
if (lockedLevel[m_impl->type] > 0)
@@ -314,11 +338,25 @@ bool NzTexture::Bind()
glBindTexture(openglTarget[m_impl->type], m_impl->id);
if (!m_impl->mipmapsUpdated)
{
glGenerateMipmap(openglTarget[m_impl->type]);
m_impl->mipmapsUpdated = true;
}
return true;
}
bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth, nzUInt8 levelCount, bool lock)
{
#if NAZARA_RENDERER_SAFE
if (m_impl && m_impl->isTarget)
{
NazaraError("Texture is a target, it cannot be recreated");
return false;
}
#endif
Destroy();
if (width == 0 || height == 0 || depth == 0)
@@ -348,7 +386,7 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt
case nzImageType_1D:
if (height > 1)
{
NazaraError("1D textures must be 1 height");
NazaraError("One dimensional texture's height must be 1");
return false;
}
@@ -390,6 +428,8 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt
}
#endif
NzContext::EnsureContext();
levelCount = std::min(levelCount, NzImage::GetMaxLevel(width, height, depth));
NzTextureImpl* impl = new NzTextureImpl;
@@ -433,6 +473,12 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt
SetMipmapRange(0, m_impl->levelCount);
SetWrapMode(nzTextureWrap_Repeat);
if (m_impl->levelCount > 1U)
{
m_impl->mipmapping = true;
m_impl->mipmapsUpdated = false;
}
if (!lock)
UnlockTexture(impl);
@@ -443,6 +489,16 @@ void NzTexture::Destroy()
{
if (m_impl)
{
#if NAZARA_RENDERER_SAFE
if (m_impl->isTarget)
{
NazaraError("Texture is a target, it cannot be destroyed");
return;
}
#endif
NzContext::EnsureContext();
glDeleteTextures(1, &m_impl->id);
delete m_impl;
m_impl = nullptr;
@@ -505,9 +561,14 @@ bool NzTexture::Download(NzImage* image) const
ptr += faceSize;
}
width = std::max(width >> 1, 1U);
height = std::max(height >> 1, 1U);
depth = std::max(depth >> 1, 1U);
if (width > 1)
width >>= 1;
if (height > 1)
height >>= 1;
if (depth > 1)
depth >>= 1;
}
UnlockTexture(m_impl);
@@ -533,15 +594,22 @@ bool NzTexture::EnableMipmapping(bool enable)
return false;
}
LockTexture(m_impl);
if (!m_impl->mipmapping && enable)
glGenerateMipmap(openglTarget[m_impl->type]);
{
GLint tex;
glGetIntegerv(openglTargetBinding[m_impl->type], &tex);
if (m_impl->id == static_cast<GLuint>(tex))
{
glGenerateMipmap(openglTarget[m_impl->type]);
m_impl->mipmapsUpdated = true;
}
else
m_impl->mipmapsUpdated = false;
}
m_impl->mipmapping = enable;
UnlockTexture(m_impl);
return true;
}
@@ -744,6 +812,19 @@ bool NzTexture::IsCubemap() const
return m_impl->type == nzImageType_Cubemap;
}
bool NzTexture::IsTarget() const
{
#if NAZARA_RENDERER_SAFE
if (!IsValid())
{
NazaraError("Texture must be valid");
return false;
}
#endif
return m_impl->isTarget;
}
bool NzTexture::IsValid() const
{
return m_impl != nullptr;
@@ -1059,7 +1140,7 @@ bool NzTexture::Update(const NzImage& image, const NzRectui& rect, unsigned int
return Update(image.GetConstPixels(level), rect, z, level);
}
/*
bool NzTexture::Update(const NzImage& image, const NzCubeui& cube, nzUInt8 level)
{
#if NAZARA_RENDERER_SAFE
@@ -1078,7 +1159,7 @@ bool NzTexture::Update(const NzImage& image, const NzCubeui& cube, nzUInt8 level
return Update(image.GetConstPixels(level), cube, level);
}
*/
bool NzTexture::Update(const nzUInt8* pixels, nzUInt8 level)
{
#if NAZARA_RENDERER_SAFE
@@ -1090,11 +1171,7 @@ bool NzTexture::Update(const nzUInt8* pixels, nzUInt8 level)
#endif
if (m_impl->type == nzImageType_3D)
{
NazaraInternalError("Not implemented yet, sorry");
return false;
//return Update(pixels, NzCube(0, 0, 0, std::max(m_impl->width >> level, 1U), std::max(m_impl->height >> level, 1U), std::max(m_impl->depth >> level, 1U)), level);
}
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);
}
@@ -1108,6 +1185,12 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int
return false;
}
if (m_impl->isTarget)
{
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");
@@ -1190,8 +1273,8 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int
return true;
}
/*
bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 level = 0)
bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 level)
{
#if NAZARA_RENDERER_SAFE
if (!IsValid())
@@ -1200,6 +1283,12 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 leve
return false;
}
if (m_impl->isTarget)
{
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");
@@ -1263,15 +1352,15 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 leve
switch (m_impl->type)
{
case nzImageType_1D:
glTexSubImage1D(GL_TEXTURE_1D, level, cube.x, cube.width, format->dataFormat, format->dataType, mirrored);
glTexSubImage1D(GL_TEXTURE_1D, level, cube.x, cube.width, format.dataFormat, format.dataType, mirrored);
break;
case nzImageType_2D:
glTexSubImage1D(GL_TEXTURE_2D, level, cube.x, cube.y, cube.width, cube.height, format->dataFormat, format->dataType, mirrored);
glTexSubImage2D(GL_TEXTURE_2D, level, cube.x, cube.y, cube.width, cube.height, format.dataFormat, format.dataType, mirrored);
break;
case nzImageType_3D:
glTexSubImage1D(GL_TEXTURE_3D, level, cube.x, cube.y, cube.z, cube.width, cube.height, cube.depth, format->dataFormat, format->dataType, mirrored);
glTexSubImage3D(GL_TEXTURE_3D, level, cube.x, cube.y, cube.z, cube.width, cube.height, cube.depth, format.dataFormat, format.dataType, mirrored);
break;
default:
@@ -1284,7 +1373,7 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 leve
return true;
}
*/
bool NzTexture::UpdateFace(nzCubemapFace face, const NzImage& image, nzUInt8 level)
{
#if NAZARA_RENDERER_SAFE
@@ -1345,6 +1434,12 @@ bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRe
return false;
}
if (m_impl->isTarget)
{
NazaraError("Texture is a target, it cannot be updated");
return false;
}
if (m_impl->type != nzImageType_Cubemap)
{
NazaraError("UpdateFace is designed for cubemaps, use Update instead");
@@ -1433,14 +1528,6 @@ unsigned int NzTexture::GetValidSize(unsigned int size)
bool NzTexture::IsFormatSupported(nzPixelFormat format)
{
#if NAZARA_RENDERER_SAFE
if (!NzPixelFormat::IsValid(format))
{
NazaraError("Invalid pixel format");
return nzPixelFormat_Undefined;
}
#endif
switch (format)
{
// Formats de base
@@ -1468,9 +1555,14 @@ bool NzTexture::IsFormatSupported(nzPixelFormat format)
return supported;
}
default:
return false;
case nzPixelFormat_Undefined:
case nzPixelFormat_Count:
break;
}
NazaraError("Invalid pixel format");
return false;
}
bool NzTexture::IsTypeSupported(nzImageType type)
@@ -1487,3 +1579,16 @@ bool NzTexture::IsTypeSupported(nzImageType type)
return false;
}
}
void NzTexture::SetTarget(bool isTarget)
{
#if NAZARA_RENDERER_SAFE
if (!IsValid())
{
NazaraInternalError("Texture must be valid");
return;
}
#endif
m_impl->isTarget = isTarget;
}