mirror of
https://github.com/leozide/leocad
synced 2025-01-18 22:26:44 +01:00
Moved texture upload to context.
This commit is contained in:
parent
a9ab7c0c64
commit
408dc6ff97
4 changed files with 154 additions and 124 deletions
|
@ -668,6 +668,125 @@ void lcContext::ClearTextureCubeMap()
|
|||
mTextureCubeMap = 0;
|
||||
}
|
||||
|
||||
void lcContext::UploadTexture(lcTexture* Texture)
|
||||
{
|
||||
if (!Texture->mTexture)
|
||||
glGenTextures(1, &Texture->mTexture);
|
||||
|
||||
constexpr int Filters[2][5] =
|
||||
{
|
||||
{ GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR },
|
||||
{ GL_NEAREST, GL_LINEAR, GL_LINEAR, GL_LINEAR, GL_LINEAR },
|
||||
};
|
||||
|
||||
const int Flags = Texture->GetFlags();
|
||||
const int FilterFlags = Flags & LC_TEXTURE_FILTER_MASK;
|
||||
const int FilterIndex = FilterFlags >> LC_TEXTURE_FILTER_SHIFT;
|
||||
const int MipIndex = Flags & LC_TEXTURE_MIPMAPS ? 0 : 1;
|
||||
|
||||
unsigned int Faces, Target;
|
||||
|
||||
if ((Flags & LC_TEXTURE_CUBEMAP) == 0)
|
||||
{
|
||||
Faces = 1;
|
||||
Target = GL_TEXTURE_2D;
|
||||
BindTexture2D(Texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
Faces = 6;
|
||||
Target = GL_TEXTURE_CUBE_MAP;
|
||||
BindTextureCubeMap(Texture);
|
||||
}
|
||||
|
||||
glTexParameteri(Target, GL_TEXTURE_WRAP_S, (Flags & LC_TEXTURE_WRAPU) ? GL_REPEAT : GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(Target, GL_TEXTURE_WRAP_T, (Flags & LC_TEXTURE_WRAPV) ? GL_REPEAT : GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, Filters[MipIndex][FilterIndex]);
|
||||
glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, Filters[1][FilterIndex]);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
|
||||
if (gSupportsAnisotropic && FilterFlags == LC_TEXTURE_ANISOTROPIC)
|
||||
glTexParameterf(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, lcMin(4.0f, gMaxAnisotropy));
|
||||
|
||||
int Format;
|
||||
switch (Texture->GetImage(0).mFormat)
|
||||
{
|
||||
default:
|
||||
case lcPixelFormat::Invalid:
|
||||
Format = 0;
|
||||
break;
|
||||
case lcPixelFormat::A8:
|
||||
Format = GL_ALPHA;
|
||||
break;
|
||||
case lcPixelFormat::L8A8:
|
||||
Format = GL_LUMINANCE_ALPHA;
|
||||
break;
|
||||
case lcPixelFormat::R8G8B8:
|
||||
Format = GL_RGB;
|
||||
break;
|
||||
case lcPixelFormat::R8G8B8A8:
|
||||
Format = GL_RGBA;
|
||||
break;
|
||||
}
|
||||
|
||||
int CurrentImage = 0;
|
||||
if (Flags & LC_TEXTURE_CUBEMAP)
|
||||
Target = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
|
||||
|
||||
for (size_t FaceIdx = 0; FaceIdx < Faces; FaceIdx++)
|
||||
{
|
||||
void* Data = Texture->GetImage(CurrentImage).mData;
|
||||
glTexImage2D(Target, 0, Format, Texture->mWidth, Texture->mHeight, 0, Format, GL_UNSIGNED_BYTE, Data);
|
||||
|
||||
if (Flags & LC_TEXTURE_MIPMAPS || FilterFlags >= LC_TEXTURE_BILINEAR)
|
||||
{
|
||||
int Width = Texture->mWidth;
|
||||
int Height = Texture->mHeight;
|
||||
int Components = Texture->GetImage(CurrentImage).GetBPP();
|
||||
|
||||
for (int Level = 1; ((Width != 1) || (Height != 1)); Level++)
|
||||
{
|
||||
int RowStride = Width * Components;
|
||||
|
||||
Width = lcMax(1, Width >> 1);
|
||||
Height = lcMax(1, Height >> 1);
|
||||
|
||||
if (Texture->GetImageCount() == Faces)
|
||||
{
|
||||
GLubyte* Out, * In;
|
||||
|
||||
In = Out = (GLubyte*)Data;
|
||||
|
||||
for (int y = 0; y < Height; y++, In += RowStride)
|
||||
for (int x = 0; x < Width; x++, Out += Components, In += 2 * Components)
|
||||
for (int c = 0; c < Components; c++)
|
||||
Out[c] = (In[c] + In[c + Components] + In[RowStride] + In[c + RowStride + Components]) / 4;
|
||||
}
|
||||
else
|
||||
Data = Texture->GetImage(++CurrentImage).mData;
|
||||
|
||||
glTexImage2D(Target, Level, Format, Width, Height, 0, Format, GL_UNSIGNED_BYTE, Data);
|
||||
}
|
||||
|
||||
if (Texture->GetImageCount() == Faces)
|
||||
CurrentImage++;
|
||||
}
|
||||
else
|
||||
CurrentImage++;
|
||||
|
||||
Target++;
|
||||
}
|
||||
|
||||
if ((Flags & LC_TEXTURE_CUBEMAP) == 0)
|
||||
ClearTexture2D();
|
||||
else
|
||||
ClearTextureCubeMap();
|
||||
}
|
||||
|
||||
void lcContext::SetColor(float Red, float Green, float Blue, float Alpha)
|
||||
{
|
||||
SetColor(lcVector4(Red, Green, Blue, Alpha));
|
||||
|
|
|
@ -172,6 +172,7 @@ public:
|
|||
void BindTextureCubeMap(const lcTexture* Texture);
|
||||
void ClearTexture2D();
|
||||
void ClearTextureCubeMap();
|
||||
void UploadTexture(lcTexture* Texture);
|
||||
|
||||
void SetColor(const lcVector4& Color)
|
||||
{
|
||||
|
|
|
@ -171,22 +171,26 @@ bool lcTexture::Load()
|
|||
|
||||
bool lcTexture::Load(const QString& FileName, int Flags)
|
||||
{
|
||||
mImages.resize(1);
|
||||
Image Image;
|
||||
|
||||
if (!mImages[0].FileLoad(FileName))
|
||||
if (!Image.FileLoad(FileName))
|
||||
return false;
|
||||
|
||||
return Load(Flags);
|
||||
SetImage(std::move(Image), Flags);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool lcTexture::Load(lcMemFile& File, int Flags)
|
||||
{
|
||||
mImages.resize(1);
|
||||
Image Image;
|
||||
|
||||
if (!mImages[0].FileLoad(File))
|
||||
if (!Image.FileLoad(File))
|
||||
return false;
|
||||
|
||||
return Load(Flags);
|
||||
SetImage(std::move(Image), Flags);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void lcTexture::SetImage(Image&& Image, int Flags)
|
||||
|
@ -195,7 +199,7 @@ void lcTexture::SetImage(Image&& Image, int Flags)
|
|||
mImages.emplace_back(std::move(Image));
|
||||
mFlags = Flags;
|
||||
|
||||
Load(Flags);
|
||||
LoadImages();
|
||||
}
|
||||
|
||||
void lcTexture::SetImage(std::vector<Image>&& Images, int Flags)
|
||||
|
@ -203,135 +207,26 @@ void lcTexture::SetImage(std::vector<Image>&& Images, int Flags)
|
|||
mImages = std::move(Images);
|
||||
mFlags = Flags;
|
||||
|
||||
Load(Flags);
|
||||
LoadImages();
|
||||
}
|
||||
|
||||
void lcTexture::Upload(lcContext* Context)
|
||||
{
|
||||
if (!NeedsUpload())
|
||||
return;
|
||||
|
||||
mWidth = mImages[0].mWidth;
|
||||
mHeight = mImages[0].mHeight;
|
||||
|
||||
if (!mTexture)
|
||||
glGenTextures(1, &mTexture);
|
||||
Context->UploadTexture(this);
|
||||
|
||||
constexpr int Filters[2][5] =
|
||||
{
|
||||
{ GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR },
|
||||
{ GL_NEAREST, GL_LINEAR, GL_LINEAR, GL_LINEAR, GL_LINEAR },
|
||||
};
|
||||
|
||||
const int FilterFlags = mFlags & LC_TEXTURE_FILTER_MASK;
|
||||
const int FilterIndex = FilterFlags >> LC_TEXTURE_FILTER_SHIFT;
|
||||
const int MipIndex = mFlags & LC_TEXTURE_MIPMAPS ? 0 : 1;
|
||||
|
||||
unsigned int Faces, Target;
|
||||
|
||||
if ((mFlags & LC_TEXTURE_CUBEMAP) == 0)
|
||||
{
|
||||
Faces = 1;
|
||||
Target = GL_TEXTURE_2D;
|
||||
Context->BindTexture2D(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Faces = 6;
|
||||
Target = GL_TEXTURE_CUBE_MAP;
|
||||
Context->BindTextureCubeMap(this);
|
||||
}
|
||||
|
||||
glTexParameteri(Target, GL_TEXTURE_WRAP_S, (mFlags & LC_TEXTURE_WRAPU) ? GL_REPEAT : GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(Target, GL_TEXTURE_WRAP_T, (mFlags & LC_TEXTURE_WRAPV) ? GL_REPEAT : GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, Filters[MipIndex][FilterIndex]);
|
||||
glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, Filters[1][FilterIndex]);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
|
||||
if (gSupportsAnisotropic && FilterFlags == LC_TEXTURE_ANISOTROPIC)
|
||||
glTexParameterf(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, lcMin(4.0f, gMaxAnisotropy));
|
||||
|
||||
int Format;
|
||||
switch (mImages[0].mFormat)
|
||||
{
|
||||
default:
|
||||
case lcPixelFormat::Invalid:
|
||||
Format = 0;
|
||||
break;
|
||||
case lcPixelFormat::A8:
|
||||
Format = GL_ALPHA;
|
||||
break;
|
||||
case lcPixelFormat::L8A8:
|
||||
Format = GL_LUMINANCE_ALPHA;
|
||||
break;
|
||||
case lcPixelFormat::R8G8B8:
|
||||
Format = GL_RGB;
|
||||
break;
|
||||
case lcPixelFormat::R8G8B8A8:
|
||||
Format = GL_RGBA;
|
||||
break;
|
||||
}
|
||||
|
||||
int CurrentImage = 0;
|
||||
if (mFlags & LC_TEXTURE_CUBEMAP)
|
||||
Target = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
|
||||
|
||||
for (size_t FaceIdx = 0; FaceIdx < Faces; FaceIdx++)
|
||||
{
|
||||
void* Data = mImages[CurrentImage].mData;
|
||||
glTexImage2D(Target, 0, Format, mWidth, mHeight, 0, Format, GL_UNSIGNED_BYTE, Data);
|
||||
|
||||
if (mFlags & LC_TEXTURE_MIPMAPS || FilterFlags >= LC_TEXTURE_BILINEAR)
|
||||
{
|
||||
int Width = mWidth;
|
||||
int Height = mHeight;
|
||||
int Components = mImages[CurrentImage].GetBPP();
|
||||
|
||||
for (int Level = 1; ((Width != 1) || (Height != 1)); Level++)
|
||||
{
|
||||
int RowStride = Width * Components;
|
||||
|
||||
Width = lcMax(1, Width >> 1);
|
||||
Height = lcMax(1, Height >> 1);
|
||||
|
||||
if (mImages.size() == Faces)
|
||||
{
|
||||
GLubyte *Out, *In;
|
||||
|
||||
In = Out = (GLubyte*)Data;
|
||||
|
||||
for (int y = 0; y < Height; y++, In += RowStride)
|
||||
for (int x = 0; x < Width; x++, Out += Components, In += 2 * Components)
|
||||
for (int c = 0; c < Components; c++)
|
||||
Out[c] = (In[c] + In[c + Components] + In[RowStride] + In[c + RowStride + Components]) / 4;
|
||||
}
|
||||
else
|
||||
Data = mImages[++CurrentImage].mData;
|
||||
|
||||
glTexImage2D(Target, Level, Format, Width, Height, 0, Format, GL_UNSIGNED_BYTE, Data);
|
||||
}
|
||||
|
||||
if (mImages.size() == Faces)
|
||||
CurrentImage++;
|
||||
}
|
||||
else
|
||||
CurrentImage++;
|
||||
|
||||
Target++;
|
||||
}
|
||||
|
||||
if ((mFlags & LC_TEXTURE_CUBEMAP) == 0)
|
||||
Context->ClearTexture2D();
|
||||
else
|
||||
Context->ClearTextureCubeMap();
|
||||
mImages.clear();
|
||||
}
|
||||
|
||||
bool lcTexture::Load(int Flags)
|
||||
bool lcTexture::LoadImages()
|
||||
{
|
||||
for (Image& Image : mImages)
|
||||
Image.ResizePow2();
|
||||
mFlags = Flags;
|
||||
|
||||
if (QThread::currentThread() == qApp->thread())
|
||||
{
|
||||
|
|
|
@ -70,6 +70,21 @@ public:
|
|||
return mTexture == 0 && !mImages.empty();
|
||||
}
|
||||
|
||||
int GetFlags() const
|
||||
{
|
||||
return mFlags;
|
||||
}
|
||||
|
||||
const Image& GetImage(int Index) const
|
||||
{
|
||||
return mImages[Index];
|
||||
}
|
||||
|
||||
size_t GetImageCount() const
|
||||
{
|
||||
return mImages.size();
|
||||
}
|
||||
|
||||
int mWidth;
|
||||
int mHeight;
|
||||
char mName[LC_TEXTURE_NAME_LEN];
|
||||
|
@ -78,7 +93,7 @@ public:
|
|||
|
||||
protected:
|
||||
bool Load();
|
||||
bool Load(int Flags);
|
||||
bool LoadImages();
|
||||
|
||||
bool mTemporary;
|
||||
QAtomicInt mRefCount;
|
||||
|
|
Loading…
Reference in a new issue