2013-08-09 06:57:18 +02:00
|
|
|
#include "lc_global.h"
|
|
|
|
#include "lc_texture.h"
|
|
|
|
#include "lc_file.h"
|
|
|
|
#include "lc_application.h"
|
|
|
|
#include "lc_library.h"
|
|
|
|
#include "image.h"
|
2013-09-02 22:31:48 +02:00
|
|
|
#include "system.h"
|
2013-08-09 06:57:18 +02:00
|
|
|
|
|
|
|
lcTexture::lcTexture()
|
|
|
|
{
|
|
|
|
mTexture = 0;
|
|
|
|
mRefCount = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
lcTexture::~lcTexture()
|
|
|
|
{
|
|
|
|
Unload();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool lcTexture::Load()
|
|
|
|
{
|
|
|
|
return lcGetPiecesLibrary()->LoadTexture(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool lcTexture::Load(const char* FileName, int Flags)
|
|
|
|
{
|
|
|
|
Image image;
|
|
|
|
|
|
|
|
if (!image.FileLoad(FileName))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return Load(image, Flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool lcTexture::Load(lcMemFile& File, int Flags)
|
|
|
|
{
|
|
|
|
Image image;
|
|
|
|
|
|
|
|
if (!image.FileLoad(File))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return Load(image, Flags);
|
|
|
|
}
|
|
|
|
|
2013-08-31 23:58:47 +02:00
|
|
|
bool lcTexture::Load(Image* images, int NumLevels, int Flags)
|
2013-08-09 06:57:18 +02:00
|
|
|
{
|
2013-08-31 23:58:47 +02:00
|
|
|
mWidth = images[0].mWidth;
|
|
|
|
mHeight = images[0].mHeight;
|
2013-08-09 06:57:18 +02:00
|
|
|
|
|
|
|
glGenTextures(1, &mTexture);
|
|
|
|
|
2013-08-31 23:58:47 +02:00
|
|
|
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 },
|
|
|
|
};
|
|
|
|
|
|
|
|
int FilterFlags = Flags & LC_TEXTURE_FILTER_MASK;
|
|
|
|
int FilterIndex = FilterFlags >> LC_TEXTURE_FILTER_SHIFT;
|
|
|
|
int MipIndex = Flags & LC_TEXTURE_MIPMAPS ? 0 : 1;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
glBindTexture(GL_TEXTURE_2D, mTexture);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (Flags & LC_TEXTURE_WRAPU) ? GL_REPEAT : GL_CLAMP);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (Flags & LC_TEXTURE_WRAPV) ? GL_REPEAT : GL_CLAMP);
|
2013-08-31 23:58:47 +02:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Filters[MipIndex][FilterIndex]);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Filters[1][FilterIndex]);
|
2013-08-09 06:57:18 +02:00
|
|
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
|
|
|
|
2013-08-31 23:58:47 +02:00
|
|
|
if (GL_SupportsAnisotropic && FilterFlags == LC_TEXTURE_ANISOTROPIC)
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, lcMin(4.0f, GL_MaxAnisotropy));
|
|
|
|
|
|
|
|
int Format;
|
|
|
|
switch (images[0].mFormat)
|
|
|
|
{
|
2013-09-02 22:31:48 +02:00
|
|
|
default:
|
|
|
|
case LC_PIXEL_FORMAT_INVALID:
|
|
|
|
LC_ASSERT(false);
|
|
|
|
Format = 0;
|
|
|
|
break;
|
|
|
|
case LC_PIXEL_FORMAT_A8:
|
2013-08-31 23:58:47 +02:00
|
|
|
Format = GL_ALPHA;
|
|
|
|
break;
|
|
|
|
case LC_PIXEL_FORMAT_L8A8:
|
|
|
|
Format = GL_LUMINANCE_ALPHA;
|
|
|
|
break;
|
|
|
|
case LC_PIXEL_FORMAT_R8G8B8:
|
|
|
|
Format = GL_RGB;
|
|
|
|
break;
|
|
|
|
case LC_PIXEL_FORMAT_R8G8B8A8:
|
|
|
|
Format = GL_RGBA;
|
|
|
|
break;
|
|
|
|
}
|
2013-08-09 06:57:18 +02:00
|
|
|
|
2013-08-31 23:58:47 +02:00
|
|
|
void* Data = images[0].mData;
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, Format, mWidth, mHeight, 0, Format, GL_UNSIGNED_BYTE, Data);
|
2013-08-09 06:57:18 +02:00
|
|
|
|
|
|
|
if (Flags & LC_TEXTURE_MIPMAPS)
|
|
|
|
{
|
|
|
|
int Width = mWidth;
|
|
|
|
int Height = mHeight;
|
2013-08-31 23:58:47 +02:00
|
|
|
int Components = images[0].GetBPP();
|
2013-08-09 06:57:18 +02:00
|
|
|
|
|
|
|
for (int Level = 1; ((Width != 1) || (Height != 1)); Level++)
|
|
|
|
{
|
|
|
|
Width = lcMax(1, Width >> 1);
|
|
|
|
Height = lcMax(1, Height >> 1);
|
|
|
|
|
2013-08-31 23:58:47 +02:00
|
|
|
if (NumLevels == 1)
|
|
|
|
{
|
|
|
|
GLubyte *Out, *In;
|
|
|
|
int RowStride = Width * Components;
|
|
|
|
|
|
|
|
In = Out = (GLubyte*)Data;
|
2013-08-09 06:57:18 +02:00
|
|
|
|
2013-08-31 23:58:47 +02:00
|
|
|
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 = images[Level].mData;
|
2013-08-09 06:57:18 +02:00
|
|
|
|
2013-08-31 23:58:47 +02:00
|
|
|
glTexImage2D(GL_TEXTURE_2D, Level, Format, Width, Height, 0, Format, GL_UNSIGNED_BYTE, Data);
|
2013-08-09 06:57:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-08-31 23:58:47 +02:00
|
|
|
bool lcTexture::Load(Image& image, int Flags)
|
|
|
|
{
|
|
|
|
image.ResizePow2();
|
|
|
|
|
|
|
|
return Load(&image, 1, Flags);
|
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
void lcTexture::Unload()
|
|
|
|
{
|
|
|
|
if (mTexture)
|
|
|
|
glDeleteTextures(1, &mTexture);
|
|
|
|
mTexture = 0;
|
|
|
|
}
|