Integrated submission from Boris Bralo:
Supported added for precompiled mip maps stored in osg::Image, and read by osg::Texture. Updates to TerraPage loader for support of compressed texture images and precompiled mip maps.
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
#include <osg/GL>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace osg {
|
||||
|
||||
@@ -131,7 +132,31 @@ class SG_EXPORT Image : public Object
|
||||
static const unsigned int computePixelSizeInBits(GLenum format,GLenum type);
|
||||
static const unsigned int computeRowWidthInBytes(int width,GLenum format,GLenum type,int packing);
|
||||
|
||||
// precomputed mipmaps stuff;
|
||||
typedef std::vector< std::size_t > MipmapDataType;
|
||||
|
||||
inline bool isMipmap() const {return !_mipmapData.empty();};
|
||||
|
||||
std::size_t getNumMipmaps() const
|
||||
{
|
||||
return _mipmapData.size()+1;
|
||||
};
|
||||
|
||||
// send offsets into data
|
||||
// It is assumed that first mipmap offset (index 0) is 0
|
||||
inline void setMipmapData(const MipmapDataType& mipmapDataVector)
|
||||
{
|
||||
_mipmapData = mipmapDataVector;
|
||||
};
|
||||
|
||||
inline unsigned char* getMipmapData(std::size_t mipmapNumber ) const
|
||||
{
|
||||
if(mipmapNumber == 0)
|
||||
return _data;
|
||||
else if(mipmapNumber < getNumMipmaps())
|
||||
return _data + _mipmapData[mipmapNumber-1];
|
||||
return 0L;
|
||||
};
|
||||
|
||||
protected :
|
||||
|
||||
@@ -148,6 +173,8 @@ class SG_EXPORT Image : public Object
|
||||
unsigned char *_data;
|
||||
|
||||
unsigned int _modifiedTag;
|
||||
|
||||
MipmapDataType _mipmapData;
|
||||
};
|
||||
|
||||
class Geode;
|
||||
|
||||
@@ -36,15 +36,22 @@ Image::Image(const Image& image,const CopyOp& copyop):
|
||||
_dataType(image._dataType),
|
||||
_packing(image._packing),
|
||||
_data(0L),
|
||||
_mipmapData(image._mipmapData),
|
||||
_modifiedTag(image._modifiedTag)
|
||||
{
|
||||
if (image._data)
|
||||
{
|
||||
unsigned int size = computeRowWidthInBytes(_s,_pixelFormat,_dataType,_packing)*_t*_r;
|
||||
int num_components =
|
||||
_pixelFormat == GL_LUMINANCE ? 1 :
|
||||
_pixelFormat == GL_LUMINANCE_ALPHA ? 2 :
|
||||
_pixelFormat == GL_RGB ? 3 :
|
||||
_pixelFormat == GL_RGBA ? 4 : 4;
|
||||
|
||||
_data = (unsigned char*) osgMalloc(size);
|
||||
int size = _s*_t*_r*num_components;
|
||||
_data = (unsigned char*) malloc(size);
|
||||
memcpy(_data,image._data,size);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Image::~Image()
|
||||
@@ -190,6 +197,8 @@ void Image::createImage(int s,int t,int r,
|
||||
GLenum format,GLenum type,
|
||||
int packing)
|
||||
{
|
||||
_mipmapData.clear();
|
||||
|
||||
unsigned int previousTotalSize = computeRowWidthInBytes(_s,_pixelFormat,_dataType,_packing)*_t*_r;
|
||||
|
||||
unsigned int newTotalSize = computeRowWidthInBytes(s,format,type,packing)*t*r;
|
||||
@@ -235,6 +244,7 @@ void Image::setImage(int s,int t,int r,
|
||||
int packing)
|
||||
{
|
||||
if (_data) ::free(_data);
|
||||
_mipmapData.clear();
|
||||
|
||||
_s = s;
|
||||
_t = t;
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
|
||||
#include <osg/GLU>
|
||||
|
||||
#ifndef PFNGLCOMPRESSEDTEXIMAGE2DARBPROC
|
||||
typedef void (APIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
|
||||
#endif
|
||||
|
||||
using namespace osg;
|
||||
|
||||
|
||||
@@ -339,6 +343,7 @@ void Texture::applyTexImage(GLenum target, Image* image, State& state) const
|
||||
static bool s_S3TC_Compression = isGLExtensionSupported("GL_EXT_texture_compression_s3tc");
|
||||
|
||||
// select the internalFormat required for the texture.
|
||||
bool compressed = false;
|
||||
GLint internalFormat = image->getInternalTextureFormat();
|
||||
switch(_internalFormatMode)
|
||||
{
|
||||
@@ -349,6 +354,7 @@ void Texture::applyTexImage(GLenum target, Image* image, State& state) const
|
||||
case(USE_ARB_COMPRESSION):
|
||||
if (s_ARB_Compression)
|
||||
{
|
||||
compressed = true;
|
||||
switch(image->getPixelFormat())
|
||||
{
|
||||
case(1): internalFormat = GL_COMPRESSED_ALPHA_ARB; break;
|
||||
@@ -369,6 +375,7 @@ void Texture::applyTexImage(GLenum target, Image* image, State& state) const
|
||||
case(USE_S3TC_DXT1_COMPRESSION):
|
||||
if (s_S3TC_Compression)
|
||||
{
|
||||
compressed = true;
|
||||
switch(image->getPixelFormat())
|
||||
{
|
||||
case(3): internalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; break;
|
||||
@@ -384,6 +391,7 @@ void Texture::applyTexImage(GLenum target, Image* image, State& state) const
|
||||
case(USE_S3TC_DXT3_COMPRESSION):
|
||||
if (s_S3TC_Compression)
|
||||
{
|
||||
compressed = true;
|
||||
switch(image->getPixelFormat())
|
||||
{
|
||||
case(3):
|
||||
@@ -399,6 +407,7 @@ void Texture::applyTexImage(GLenum target, Image* image, State& state) const
|
||||
case(USE_S3TC_DXT5_COMPRESSION):
|
||||
if (s_S3TC_Compression)
|
||||
{
|
||||
compressed = true;
|
||||
switch(image->getPixelFormat())
|
||||
{
|
||||
case(3):
|
||||
@@ -421,33 +430,102 @@ void Texture::applyTexImage(GLenum target, Image* image, State& state) const
|
||||
// when use 16 bit textures rather than 24/32bit textures.
|
||||
// internalFormat = GL_RGBA4;
|
||||
|
||||
// an experiment to look at the changes in performance
|
||||
// when use 16 bit textures rather than 24/32bit textures.
|
||||
// internalFormat = GL_RGBA4;
|
||||
static PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2D_ptr =
|
||||
(PFNGLCOMPRESSEDTEXIMAGE2DARBPROC)getGLExtensionFuncPtr("glCompressedTexImage2DARB");
|
||||
|
||||
if (_subloadMode == OFF) {
|
||||
if( _min_filter == LINEAR || _min_filter == NEAREST )
|
||||
{
|
||||
glTexImage2D( target, 0, internalFormat,
|
||||
image->s(), image->t(), 0,
|
||||
(GLenum)image->getPixelFormat(),
|
||||
(GLenum)image->getDataType(),
|
||||
image->data() );
|
||||
if ( !compressed )
|
||||
{
|
||||
glTexImage2D( target, 0, internalFormat,
|
||||
image->s(), image->t(), 0,
|
||||
(GLenum)image->getPixelFormat(),
|
||||
(GLenum)image->getDataType(),
|
||||
image->data() );
|
||||
|
||||
// just estimate estimate it right now..
|
||||
// note, ignores texture compression..
|
||||
_textureObjectSize = image->s()*image->t()*4;
|
||||
// just estimate estimate it right now..
|
||||
// note, ignores texture compression..
|
||||
_textureObjectSize = image->s()*image->t()*4;
|
||||
}
|
||||
else if(glCompressedTexImage2D_ptr)
|
||||
{
|
||||
GLint blockSize = ( internalFormat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ? 8 : 16 );
|
||||
GLint size = ((image->s()+3)/4)*((image->t()+3)/4)*blockSize;
|
||||
glCompressedTexImage2D_ptr(target, 0, internalFormat,
|
||||
image->s(), image->t(),0,
|
||||
size,
|
||||
image->data());
|
||||
|
||||
_textureObjectSize = size;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
gluBuild2DMipmaps( target, internalFormat,
|
||||
if(!image->isMipmap())
|
||||
{
|
||||
gluBuild2DMipmaps( target, internalFormat,
|
||||
image->s(),image->t(),
|
||||
(GLenum)image->getPixelFormat(), (GLenum)image->getDataType(),
|
||||
image->data() );
|
||||
// just estimate size it right now..
|
||||
// crude x2 multiplier to account for minmap storage.
|
||||
// note, ignores texture compression..
|
||||
_textureObjectSize = image->s()*image->t()*4;
|
||||
}
|
||||
else
|
||||
{
|
||||
_textureObjectSize = 0;
|
||||
size_t no_mipmaps = image->getNumMipmaps();
|
||||
int width = image->s();
|
||||
int height = image->t();
|
||||
|
||||
if( !compressed )
|
||||
{
|
||||
for( size_t k = 0 ; k < no_mipmaps && (width || height) ;k++)
|
||||
{
|
||||
|
||||
if (width == 0)
|
||||
width = 1;
|
||||
if (height == 0)
|
||||
height = 1;
|
||||
|
||||
// just estimate size it right now..
|
||||
// crude x2 multiplier to account for minmap storage.
|
||||
// note, ignores texture compression..
|
||||
_textureObjectSize = image->s()*image->t()*4;
|
||||
glTexImage2D( target, k, internalFormat,
|
||||
width, height, 0,
|
||||
(GLenum)image->getPixelFormat(),
|
||||
(GLenum)image->getDataType(),
|
||||
image->getMipmapData(k));
|
||||
|
||||
_textureObjectSize += width*height*4;
|
||||
width >>= 1;
|
||||
height >>= 1;
|
||||
}
|
||||
}
|
||||
else if(glCompressedTexImage2D_ptr)
|
||||
{
|
||||
GLint blockSize = ( internalFormat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ? 8 : 16 );
|
||||
GLint size = 0;
|
||||
for( size_t k = 0 ; k < no_mipmaps && (width || height) ;k++)
|
||||
{
|
||||
if (width == 0)
|
||||
width = 1;
|
||||
if (height == 0)
|
||||
height = 1;
|
||||
|
||||
size = ((width+3)/4)*((height+3)/4)*blockSize;
|
||||
glCompressedTexImage2D_ptr(target, k, internalFormat,
|
||||
width, height, 0, size, image->getMipmapData(k));
|
||||
|
||||
_textureObjectSize += size;
|
||||
width >>= 1;
|
||||
height >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ Texture* txp::GetLocalTexture(trpgrImageHelper& image_helper, trpgLocalMaterial*
|
||||
trpgTexture::ImageType type;
|
||||
tex->GetImageType(type);
|
||||
|
||||
Texture::InternalFormatMode internalFormatMode = Texture::USE_IMAGE_DATA_FORMAT;
|
||||
Texture::InternalFormatMode internalFormat = Texture::USE_IMAGE_DATA_FORMAT;
|
||||
|
||||
GLenum gltype = (GLenum)-1;
|
||||
switch(type)
|
||||
@@ -87,33 +87,44 @@ Texture* txp::GetLocalTexture(trpgrImageHelper& image_helper, trpgLocalMaterial*
|
||||
break;
|
||||
case trpgTexture::trpg_DXT1:
|
||||
if(depth == 3)
|
||||
{
|
||||
gltype = GL_RGB;
|
||||
}
|
||||
else
|
||||
{
|
||||
gltype = GL_RGBA;
|
||||
internalFormatMode = Texture::USE_S3TC_DXT1_COMPRESSION;
|
||||
}
|
||||
internalFormat = Texture::USE_S3TC_DXT1_COMPRESSION;
|
||||
break;
|
||||
case trpgTexture::trpg_DXT3:
|
||||
if(depth == 3)
|
||||
{
|
||||
gltype = GL_RGB;
|
||||
}
|
||||
else
|
||||
{
|
||||
gltype = GL_RGBA;
|
||||
internalFormatMode = Texture::USE_S3TC_DXT3_COMPRESSION;
|
||||
}
|
||||
internalFormat = Texture::USE_S3TC_DXT3_COMPRESSION;
|
||||
break;
|
||||
case trpgTexture::trpg_DXT5:
|
||||
if(depth == 3)
|
||||
{
|
||||
gltype = GL_RGB;
|
||||
}
|
||||
else
|
||||
{
|
||||
gltype = GL_RGBA;
|
||||
internalFormatMode = Texture::USE_S3TC_DXT5_COMPRESSION;
|
||||
}
|
||||
internalFormat = Texture::USE_S3TC_DXT5_COMPRESSION;
|
||||
break;
|
||||
}
|
||||
|
||||
if(gltype!=(GLenum)-1)
|
||||
{
|
||||
osg_texture = new Texture();
|
||||
osg_texture->setInternalFormatMode(internalFormatMode);
|
||||
osg_texture->setInternalFormatMode(internalFormat);
|
||||
|
||||
|
||||
Image* image = new Image;
|
||||
char* data = 0L;
|
||||
|
||||
@@ -130,21 +141,38 @@ Texture* txp::GetLocalTexture(trpgrImageHelper& image_helper, trpgLocalMaterial*
|
||||
else
|
||||
image_helper.GetLocalGL(tex,data,size);
|
||||
|
||||
image->setImage(s.x,s.y,1,depth,
|
||||
gltype,GL_UNSIGNED_BYTE,
|
||||
(unsigned char*)data);
|
||||
}
|
||||
else
|
||||
{
|
||||
int32 size = tex->CalcTotalSize();
|
||||
trpgTexture* tmp_tex = const_cast<trpgTexture*>(tex);
|
||||
|
||||
for( int j = 1 ; j <= num_mipmaps;j++ )
|
||||
size -= tmp_tex->MipLevelSize(j);//s.x*s.y*depth;
|
||||
|
||||
data = (char*)::malloc(size);
|
||||
|
||||
if(locmat)
|
||||
image_helper.GetImageForLocalMat(locmat,data,size);
|
||||
else
|
||||
image_helper.GetLocalGL(tex,data,size);
|
||||
|
||||
// Load entire texture including mipmaps
|
||||
image->setImage(s.x,s.y,1,depth,
|
||||
gltype,GL_UNSIGNED_BYTE,
|
||||
(unsigned char*)data);
|
||||
|
||||
// now set mipmap data (offsets into image raw data)
|
||||
Image::MipmapDataType mipmaps;
|
||||
// number of offsets in osg is one less than num_mipmaps
|
||||
// because it's assumed that first offset iz 0
|
||||
mipmaps.resize(num_mipmaps-1);
|
||||
for( int k = 1 ; k < num_mipmaps;k++ )
|
||||
{
|
||||
mipmaps[k-1] = tmp_tex->MipLevelOffset(k);
|
||||
}
|
||||
image->setMipmapData(mipmaps);
|
||||
|
||||
}
|
||||
// AAAARRRGH! TOOK ME 2 DAYS TO FIGURE IT OUT
|
||||
// EVERY IMAGE HAS TO HAVE UNIQUE NAME FOR OPTIMIZER NOT TO OPTIMIZE IT OFF
|
||||
@@ -155,10 +183,6 @@ Texture* txp::GetLocalTexture(trpgrImageHelper& image_helper, trpgLocalMaterial*
|
||||
|
||||
image->setFileName(unique_name);
|
||||
|
||||
image->setImage(s.x,s.y,1,depth,
|
||||
gltype,GL_UNSIGNED_BYTE,
|
||||
(unsigned char*)data);
|
||||
|
||||
osg_texture->setImage(image);
|
||||
}
|
||||
return osg_texture;
|
||||
|
||||
Reference in New Issue
Block a user