PDA

View Full Version : Simple Code to load DXT textures



patbier
12-09-2005, 02:50 AM
Hello, I was looking for a simple sample, showing how to load a DXT texture (made with Nvidia photoshop plugin or Ati Compressonator).

I didn't find exactly what i searched.
So I wrote my own code, based on code found.

I have a Segmentation fault when the glCompressedTexImage2DARB is called

Please can someone help me ?



const unsigned long FOURCC_DXT1 = 0x31545844; //(MAKEFOURCC('D','X','T','1'))
const unsigned long FOURCC_DXT3 = 0x33545844; //(MAKEFOURCC('D','X','T','3'))
const unsigned long FOURCC_DXT5 = 0x35545844; //(MAKEFOURCC('D','X','T','5'))

typedef struct
{
GLsizei width;
GLsizei height;
GLint components;
GLenum format;
int numMipMaps;
GLubyte *pixels;
}
DDS_IMAGE_DATA;

typedef struct
{
unsigned long dwSize;
unsigned long dwFlags;
unsigned long dwFourCC;
unsigned long dwRGBBitCount;
unsigned long dwRBitMask;
unsigned long dwGBitMask;
unsigned long dwBBitMask;
unsigned long dwABitMask;
}
DDS_PIXELFORMAT;

typedef struct
{
unsigned long dwSize;
unsigned long dwFlags;
unsigned long dwHeight;
unsigned long dwWidth;
unsigned long dwLinearSize;
unsigned long dwDepth;
unsigned long dwMipMapCount;
unsigned long dwReserved1[11];
DDS_PIXELFORMAT ddpfPixelFormat;
unsigned long dwCaps1;
unsigned long dwCaps2;
unsigned long dwReserved2[3];
}
DDSURFACEDESC2;

PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB;

DDS_IMAGE_DATA* loadDDSTextureFile( const char *filename )
{
DDS_IMAGE_DATA *pDDSImageData;
DDSURFACEDESC2 ddsd;
char filecode[4];
FILE *pFile;
int factor;
int bufferSize;

// Open the file
pFile = fopen( filename, "rb" );

if( pFile == NULL )
{
fclose( pFile );return 0;
}

// Verify the file is a true .dds file
fread( filecode, 1, 4, pFile );

if( strncmp( filecode, "DDS ", 4 ) != 0 )
{
fclose( pFile );
return 0;
}

// Get the surface descriptor
fread( &ddsd, sizeof(ddsd), 1, pFile );

pDDSImageData = (DDS_IMAGE_DATA*) malloc(sizeof(DDS_IMAGE_DATA));

memset( pDDSImageData, 0, sizeof(DDS_IMAGE_DATA) );

if( ddsd.ddpfPixelFormat.dwFourCC ==FOURCC_DXT1)
{
// DXT1's compression ratio is 8:1
pDDSImageData->format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
factor = 2;
pDDSImageData->components = 3;
}
else
{
if( ddsd.ddpfPixelFormat.dwFourCC ==FOURCC_DXT3)
{
// DXT3's compression ratio is 4:1
pDDSImageData->format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
factor = 4;
pDDSImageData->components = 4;
}
else
{
if( ddsd.ddpfPixelFormat.dwFourCC ==FOURCC_DXT5)
{
// DXT5's compression ratio is 4:1
pDDSImageData->format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
factor = 4;
pDDSImageData->components = 4;
}
else
{
return 0;
}
}
}

if( ddsd.dwLinearSize == 0 )
{
return 0;
}

if( ddsd.dwMipMapCount > 1 )
bufferSize = ddsd.dwLinearSize * factor;
else
bufferSize = ddsd.dwLinearSize;

pDDSImageData->pixels = (unsigned char*)malloc(bufferSize * sizeof(unsigned char));

fread( pDDSImageData->pixels, 1, bufferSize, pFile );

// Close the file
fclose( pFile );

pDDSImageData->width = ddsd.dwWidth;
pDDSImageData->height = ddsd.dwHeight;
pDDSImageData->numMipMaps = ddsd.dwMipMapCount;
return pDDSImageData;
}


int loadImage(int *l, char *file,int blur)
{
int f;
DDS_IMAGE_DATA *pDDSImageData;
if (blur) f=GL_LINEAR; else f=GL_NEAREST;

pDDSImageData = loadDDSTextureFile(file);

if( pDDSImageData != NULL )
{
int nHeight = pDDSImageData->height;
int nWidth = pDDSImageData->width;
int nNumMipMaps = pDDSImageData->numMipMaps;
int nSize;
int nOffset = 0;
int i;
GLuint g_compressedTextureID = -1;
int nBlockSize;

if( pDDSImageData->format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT )
nBlockSize = 8;
else
nBlockSize = 16;

glGenTextures( 1, &g_compressedTextureID );
glBindTexture( GL_TEXTURE_2D, g_compressedTextureID );
*l = g_compressedTextureID;

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, f );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, f );

// Load the mip-map levels

unsigned int size = (((nWidth >> 2) + 3) & ~3) * (((nHeight >> 2) + 3) & ~3) * nBlockSize;
if (pDDSImageData->pixels != NULL)
{

glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, pDDSImageData->format,
nWidth, nHeight, 0,
size,
pDDSImageData->pixels);

}
for(i = 0; i < nNumMipMaps; ++i )
{
if( nWidth == 0 ) nWidth = 1;
if( nHeight == 0 ) nHeight = 1;

nSize = ((nWidth+3)/4) * ((nHeight+3)/4) * nBlockSize;

glCompressedTexImage2DARB( GL_TEXTURE_2D,
i,
pDDSImageData->format,
nWidth,
nHeight,
0,
nSize,
pDDSImageData->pixels + nOffset );

nOffset += nSize;

// Half the image size for the next mip-map level...
nWidth = (nWidth / 2);
nHeight = (nHeight / 2);
}
}

if( pDDSImageData != NULL )
{
if( pDDSImageData->pixels != NULL )
free( pDDSImageData->pixels );

free( pDDSImageData );
}

return 1;
}

patbier
12-10-2005, 02:42 AM
do you think this question could be answered in the "OpenGL coding: advanced" ?