It’s quite large just to see a particular bit, I’m actually making a texture superclass so I don’t think you’ll find it very useful, but anyway, here it goes…
I created the texture like this :
Texture * tex = new Texture2D(256,256,GL_RGB16F_ARB,GL_RGB,GL_HALF_FLOAT_ARB,vecdata,GL_TEXTURE_2D,"name",false,false);
which calls the ctor and does these :
_type = TEX2D;
bind();
_maxMiplevel = (loadAsRect) ? 0 : GLuint(texdata.size() - 1);
// Check if compressed
if((_internalFormat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT) ||
(_internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ||
(_internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) ||
(_internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT))
{
_isCompressed = true;
// Load all mipmap levels
unsigned miplevel = 0;
while(miplevel <= _maxMiplevel)
{
const unsigned char * tmp_data = texdata[miplevel].data;
const double adjust = 1.0 / pow(2.0,int(miplevel));
unsigned tmp_w = unsigned(_width * adjust),
tmp_h = unsigned(_height * adjust);
glCompressedTexImage2D(_target,miplevel,_internalFormat,tmp_w,tmp_h,0,texdata[miplevel].size,tmp_data);
++miplevel;
}
}
else
{
_isCompressed = false;
// Load all mipmap levels
if(genMipmaps)
glTexParameteri(_target,GL_GENERATE_MIPMAP,GL_TRUE);
unsigned miplevel = 0;
while(miplevel <= _maxMiplevel)
{
const unsigned char * tmp_data = texdata[miplevel].data;
const double adjust = 1.0 / pow(2.0,int(miplevel));
unsigned tmp_w = unsigned(_width * adjust),
tmp_h = unsigned(_height * adjust);
glTexImage2D(_target,miplevel,_internalFormat,tmp_w,tmp_h,0,_pixelFormat,_datatype,tmp_data);
++miplevel;
}
glTexParameteri(_target,GL_GENERATE_MIPMAP,GL_FALSE);
}
if(loadAsRect)
{
setParam(GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
setParam(GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
setParam(GL_TEXTURE_MIN_FILTER,GL_NEAREST);
setParam(GL_TEXTURE_MAG_FILTER,GL_NEAREST);
}
else
{
setParam(GL_TEXTURE_WRAP_S,GL_REPEAT);
setParam(GL_TEXTURE_WRAP_T,GL_REPEAT);
if(_maxMiplevel)
setParam(GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
else
setParam(GL_TEXTURE_MIN_FILTER,GL_LINEAR);
setParam(GL_TEXTURE_MAG_FILTER,GL_LINEAR);
}
// Compute bytes per texel
GLint vals[7];
glGetTexLevelParameteriv(_target,0,GL_TEXTURE_RED_SIZE,&vals[0]);
glGetTexLevelParameteriv(_target,0,GL_TEXTURE_GREEN_SIZE,&vals[1]);
glGetTexLevelParameteriv(_target,0,GL_TEXTURE_BLUE_SIZE,&vals[2]);
glGetTexLevelParameteriv(_target,0,GL_TEXTURE_ALPHA_SIZE,&vals[3]);
glGetTexLevelParameteriv(_target,0,GL_TEXTURE_LUMINANCE_SIZE,&vals[4]);
glGetTexLevelParameteriv(_target,0,GL_TEXTURE_INTENSITY_SIZE,&vals[5]);
glGetTexLevelParameteriv(_target,0,GL_TEXTURE_DEPTH_SIZE,&vals[6]);
_bytesPerTexel += vals[0];
_bytesPerTexel += vals[1];
_bytesPerTexel += vals[2];
_bytesPerTexel += vals[3];
_bytesPerTexel += vals[4];
_bytesPerTexel += vals[5];
_bytesPerTexel += vals[6];
_bytesPerTexel >>= 3;
I get the data size with this :
void Texture2D :: dlData(void * buffer,const GLuint miplevel) const
{
bind();
if(_isCompressed)
{
glGetCompressedTexImage(_target,miplevel,buffer);
}
else
glGetTexImage(_target,miplevel,_pixelFormat,_datatype,buffer);
}
And I save it like this :
bool TextureIO :: _saveTEX(const Texture * tex,
const std::string& fname)
{
TEX_header header = tex->getTEXheader();
FILE * fp = fopen(fname.c_str(),"wb");
if( fp == NULL )
{
CKLOG(string("Error opening file ") + fname,0);
return 0;
}
// Write header
fwrite(&header,sizeof(header),1,fp);
if(!_saveMipmaps)
header.mipcount = 1;
unsigned faces = (header.textype == TEXCUBE) ? 6 : 1;
for(unsigned i=0;i<faces;++i)
{
for(unsigned j=0;j<header.mipcount;++j)
{
// write mipmap level
unsigned size = tex->dataSize(j);
unsigned char * data = MemMgrRaw::instance()->allocate<unsigned char>(size);
if(header.textype == TEXCUBE)
tex->dlData(data,CubemapFace(i),j);
else
tex->dlData(data,j);
fwrite(&size,sizeof(unsigned),1,fp);
fwrite(data,sizeof(unsigned char),size,fp);
MemMgrRaw::instance()->free<unsigned char>(data);
}
}
fclose(fp);
return true;
}
And I load it like this :
Texture * TextureIO :: _loadTEX(const std::string& fname)
{
// Log Event : Not Implemented Yet!
FILE * fp = fopen(fname.c_str(),"rb");
if( fp == NULL )
{
CKLOG(string("Error opening file ") + fname,0);
return 0;
}
TEX_header header;
size_t read = fread(&header,sizeof(header),1,fp);
if((!read) || (header.magic != 1234))
{
CKLOG(string("Invalid TEX header in file ") + fname,0);
return 0;
}
vector<vector<MipmapLevel> > data;
unsigned faces = (header.textype == TEXCUBE) ? 6 : 1;
if(header.textype != TEX3D)
header.depth = 1;
// Get the size of mip 0 of the tex (or 1 of 6 in cubemaps)
unsigned size(0);
// Get the data
for(unsigned i=0;i<faces;++i)
{
vector<MipmapLevel> single_data;
for(unsigned j=0;j<header.mipcount;++j)
{
fread(&size,sizeof(unsigned),1,fp);
MipmapLevel miplevel(MemMgrRaw::instance()->allocate<unsigned char>(size),size);
fread(miplevel.data,1,size,fp);
if(_genMipmaps || (!j))
single_data.push_back(miplevel);
else
MemMgrRaw::instance()->free<unsigned char>(miplevel.data);
}
data.push_back(single_data);
}
fclose(fp);
header.mipcount = 1;
Texture * tex(NULL);
bool genMips = (header.mipcount > 1) ? false : _genMipmaps;
// Create the textures
switch(header.textype)
{
case TEX1D:
break;
case TEX2D :
{
bool loadrect = (header.compressed || _genMipmaps) ? false : _loadAsRect;
unsigned target = loadrect ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D;
tex = new Texture2D(header.width,header.height,header.ifmt,header.pfmt,
header.datatype,data[0],target,truncDir(fname),genMips,loadrect);
}
break;
case TEX3D :
tex = new Texture3D(header.width,header.height,header.depth,header.ifmt,header.pfmt,
header.datatype,data[0],GL_TEXTURE_3D,truncDir(fname),genMips);
break;
case TEXCUBE :
tex = new TextureCube(header.width,header.height,header.ifmt,header.pfmt,
header.datatype,data,GL_TEXTURE_CUBE_MAP,truncDir(fname),genMips);
break;
default :
assert(0);
}
// Release memory
for(unsigned i=0;i<faces;++i)
for(unsigned j=0;j<header.mipcount;++j)
MemMgrRaw::instance()->free<unsigned char>(data[i][j].data);
return tex;
}
I don’t expect of you to read all this stuff, but you asked for it