ran into the same old problem recently: even 5 years later a lot of computers still have OpenGl 1.1 installed, so Irrlicht programs with OpenGL don't
run out-of-the-box.
But now the good news: I was able to fix the opengl 1.1 texture problem with some simple adjustments in COpenGLTexture::copyTexture(bool newTexture) and void COpenGLTexture::getImageData(IImage* image). Well, at least this works for Irrlicht 1.3, don't know if the newer Irrlicht versions have many changes in this code.
Here is the code, it would be great if this could be integrated in the newer Irrlicht versions, making it a lot more compatible.:
Code: Select all
void COpenGLTexture::getImageData(IImage* image)
{
if (!image)
{
os::Printer::log("No image for OpenGL texture.", ELL_ERROR);
return;
}
ImageSize = image->getDimension();
OriginalSize = ImageSize;
if (atof((c8*)glGetString(GL_VERSION)) < 1.1999) // fix for opengl 1.1
{
core::dimension2d<s32> nImageSize;
nImageSize.Width = getTextureSizeFromSurfaceSize(ImageSize.Width);
nImageSize.Height = getTextureSizeFromSurfaceSize(ImageSize.Height);
if (!nImageSize.Width || !nImageSize.Height || !ImageSize.Width || !ImageSize.Height)
{
os::Printer::log("Could not create OpenGL Texture.", ELL_ERROR);
return;
}
ImageData = new s32[nImageSize.Width * nImageSize.Height];
if (nImageSize == ImageSize)
{
if (image->getColorFormat() == ECF_A8R8G8B8)
{
s32 s = nImageSize.Width * nImageSize.Height;
s32 *t = (s32*)image->lock();
for (s32 i=0; i<s; ++i) ImageData[i] = t[i];
image->unlock();
}
else
{
// slow converting
for (s32 x=0; x<ImageSize.Width; ++x)
for (s32 y=0; y<ImageSize.Height; ++y)
ImageData[y*nImageSize.Width + x] = image->getPixel(x,y).color;
}
}
else
{
// scale texture
s32* source = (s32*)image->lock();
f32 sourceXStep = (f32)ImageSize.Width / (f32)nImageSize.Width;
f32 sourceYStep = (f32)ImageSize.Height / (f32)nImageSize.Height;
f32 sy;
if (image->getColorFormat() == ECF_A8R8G8B8)
{
// copy texture scaling
for (s32 x=0; x<nImageSize.Width; ++x)
{
sy = 0.0f;
for (s32 y=0; y<nImageSize.Height; ++y)
{
ImageData[(s32)(y*nImageSize.Width + x)] = source[(s32)(((s32)sy)*ImageSize.Width + x*sourceXStep)];
sy+=sourceYStep;
}
}
}
else
{
// convert texture scaling, slow
for (s32 x=0; x<nImageSize.Width; ++x)
{
sy = 0.0f;
for (s32 y=0; y<nImageSize.Height; ++y)
{
ImageData[(s32)(y*nImageSize.Width + x)] =
image->getPixel((s32)(x*sourceXStep), (s32)sy).color;
sy+=sourceYStep;
}
}
}
}
ImageSize = nImageSize;
return;
}
if ( !ImageSize.Width || !ImageSize.Height)
{
os::Printer::log("Invalid size of image for OpenGL Texture.", ELL_ERROR);
return;
}
core::dimension2d<s32> nImageSize;
if (Driver && Driver->queryFeature(EVDF_TEXTURE_NPOT))
nImageSize=ImageSize;
else
{
nImageSize.Width = getTextureSizeFromSurfaceSize(ImageSize.Width);
nImageSize.Height = getTextureSizeFromSurfaceSize(ImageSize.Height);
}
SurfaceHasSameSize=ImageSize==nImageSize;
s32 bpp=0;
if (image->getColorFormat()==ECF_R8G8B8)
{
bpp=4;
ColorFormat = ECF_A8R8G8B8;
}
else
{
bpp=image->getBytesPerPixel();
ColorFormat = image->getColorFormat();
}
Pitch = nImageSize.Width*bpp;
ImageData = new s32[Pitch * nImageSize.Height];
if (nImageSize == ImageSize)
{
void* source = image->lock();
if (image->getColorFormat()==ECF_R8G8B8)
CColorConverter::convert_R8G8B8toA8R8G8B8(source,ImageSize.Width*ImageSize.Height,ImageData);
else
memcpy(ImageData,source,Pitch*nImageSize.Height);
}
else
{
u8* source = (u8*)image->lock();
// scale texture
f32 sourceXStep = (f32)ImageSize.Width / (f32)nImageSize.Width;
f32 sourceYStep = (f32)ImageSize.Height / (f32)nImageSize.Height;
f32 sx,sy;
// copy texture scaling
sy = 0.0f;
for (s32 y=0; y<nImageSize.Height; ++y)
{
sx = 0.0f;
for (s32 x=0; x<nImageSize.Width; ++x)
{
s32 i=((s32)(((s32)sy)*ImageSize.Width + sx));
if (image->getColorFormat()==ECF_R8G8B8)
{
i*=3;
((s32*)ImageData)[y*nImageSize.Width + x]=SColor(255,source[i],source[i+1],source[i+2]).color;
}
else
memcpy(&ImageData[(y*nImageSize.Width + x)*bpp],&source[i*bpp],bpp);
sx+=sourceXStep;
}
sy+=sourceYStep;
}
}
image->unlock();
ImageSize = nImageSize;
}
void COpenGLTexture::copyTexture(bool newTexture)
{
if (atof((c8*)glGetString(GL_VERSION)) < 1.1999) //fix for opengl 1.1
{
glBindTexture(GL_TEXTURE_2D, TextureName);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ImageSize.Width, ImageSize.Height, 0, GL_BGRA_EXT , GL_UNSIGNED_BYTE, ImageData);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if (HasMipMaps)
{
s32 ret = 0;
#ifndef DISABLE_MIPMAPPING
ret = gluBuild2DMipmaps(GL_TEXTURE_2D, 4, ImageSize.Width, ImageSize.Height, GL_BGRA_EXT, GL_UNSIGNED_BYTE, ImageData);
#endif
if (ret)
{
#ifndef DISABLE_MIPMAPPING
os::Printer::log("Could not create OpenGL texture mip maps.", (c8*)gluErrorString(ret), ELL_ERROR);
#else
os::Printer::log("Did not create OpenGL texture mip maps.", ELL_ERROR);
#endif
}
else
{
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
}
}
return;
}
glBindTexture(GL_TEXTURE_2D, TextureName);
if (Driver->testGLError())
os::Printer::log("Could not bind Texture", ELL_ERROR);
switch (ColorFormat)
{
case ECF_A1R5G5B5:
InternalFormat=GL_RGBA;
PixelFormat=GL_BGRA_EXT;
PixelType=GL_UNSIGNED_SHORT_1_5_5_5_REV;
break;
case ECF_R5G6B5:
InternalFormat=GL_RGB;
PixelFormat=GL_RGB;
PixelType=GL_UNSIGNED_SHORT_5_6_5;
break;
case ECF_R8G8B8:
InternalFormat=GL_RGB8;
PixelFormat=GL_RGB;
PixelType=GL_UNSIGNED_BYTE;
break;
case ECF_A8R8G8B8:
InternalFormat=GL_RGBA;
PixelFormat=GL_BGRA_EXT;
PixelType=GL_UNSIGNED_INT_8_8_8_8_REV;
break;
default:
os::Printer::log("Unsupported texture format", ELL_ERROR);
break;
}
#ifndef DISABLE_MIPMAPPING
if (HasMipMaps && Driver && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE))
{
// automatically generate and update mipmaps
glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE );
AutomaticMipmapUpdate=true;
}
else
{
AutomaticMipmapUpdate=false;
regenerateMipMapLevels();
}
if (HasMipMaps) // might have changed in regenerateMipMapLevels
{
// enable bilinear mipmap filter
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
else
#else
HasMipMaps=false;
os::Printer::log("Did not create OpenGL texture mip maps.", ELL_ERROR);
#endif
{
// enable bilinear filter without mipmaps
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
if (newTexture)
glTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, ImageSize.Width,
ImageSize.Height, 0, PixelFormat, PixelType, ImageData);
else
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, ImageSize.Width,
ImageSize.Height, PixelFormat, PixelType, ImageData);
if (Driver->testGLError())
os::Printer::log("Could not glTexImage2D", ELL_ERROR);
}