S3TC, width has to be = height? Please help

I just got it done to use S3TC compressed DDS files. All of my textures worked fine… except the 512x128 one. When I stretched it to 512x512 it worked as well. I heard of others in DirectX you can also use S3TC textures with uneven width and height… is this in gl possible as well? I don’t know what’s wrong with it or with my code, here some snipplets:

  img=LoadDDS(fn.strdata);

  int blockSize = (img->miFormat == 0) ? 8 : 16;				
  width=img->miWidth;
  height=img->miHeight;
  int offset=0, i, size, format;

  switch(img->miFormat)
  {
  case 0:
  	format=GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break;
  case 1:
  	format=GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break;
  case 2:
  	format=GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break;
  };
  
  for (i = 0; i < img->miMipMaps && (width | | height); ++i)
  {
  	if(!width)
  		width = 1;
  	if(!height)
  		height = 1;

  	size = ((width+3)/4)*((height+3)/4)*blockSize;

  	glCompressedTexImage2DARB(GL_TEXTURE_2D, i, format, width, height, 
  	  0, size, (char*)img->mlpData + offset);

  	offset += size;
  	width >>= 1;
  	height >>= 1;
  }

  free(img->mlpData);

  width=img->miWidth;
  height=img->miHeight;

  if(img->miMipMaps>1)
  	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
  else
  	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

  mTextures[mdwTextureCount-1].miSize=img->miDatasize;

CDDSImage* LoadDDS(char *fn)
{
DDSURFACEDESC2 ddsd;
char filecode[4];
FILE *fp;
int factor;

/* try to open the file */
fp = fopen(fn, “rb”);
if (fp == NULL)
return NULL;

result=new CDDSImage;

/* verify the type of file */
fread(filecode, 1, 4, fp);
if (strncmp(filecode, "DDS ", 4) != 0) {
fclose(fp);
return NULL;
}

/* get the surface desc */
fread(&ddsd, sizeof(ddsd), 1, fp);

switch(ddsd.ddpfPixelFormat.dwFourCC)
{
case FOURCC_DXT1:
result->miFormat = 0; //GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
factor = 2;
break;
case FOURCC_DXT3:
result->miFormat = 1; //GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
factor = 4;
break;
case FOURCC_DXT5:
result->miFormat = 2; //GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
factor = 4;
break;
default:
return NULL;
}

/* how big is it going to be including all mipmaps? /
result->miDatasize = ddsd.dwMipMapCount > 1 ? ddsd.dwLinearSize * factor : ddsd.dwLinearSize;
result->mlpData = (void
)malloc(result->miDatasize);
fread(result->mlpData, 1, result->miDatasize, fp);
/* close the file pointer */
fclose(fp);

result->miWidth = ddsd.dwWidth;
result->miHeight = ddsd.dwHeight;
result->miColorComponents = (ddsd.ddpfPixelFormat.dwFourCC == FOURCC_DXT1) ? 3 : 4;
result->miMipMaps = ddsd.dwMipMapCount;

/* return data */
return result;
};

I hope someone can help =/…

  • Anatrax -

p.s. The program does not crash or so. Also glGetError() results that all is fine, but the texture is just totally white… so was not loadable.

[This message has been edited by Anatrax (edited 06-26-2002).]

Can you make the problem texture available?

It works with none for me, I tried around 20 ones in lots of possible height/width relations. The BMP version of it no problem, but after converting it… well.
www.lyxion.com/Anatrax/detail_nc.dds

Looks like you don’t have enough mipmaps. In OpenGL you need to define all mipmap levels down to the 1x1 pixel mipmap. In that image you posted there are only mipmaps down to 1x16.

Ok, fixed it now, thanks. Am simply using my last mipmap now for all remaining ones downto 1x1.

Code: (awaits that all mipmaps till either width and height reached 1 are existing)

  for (i = 0; (width &#0124; &#0124; height); ++i)
  {
  	if(!width)
  		width = 1;
  	if(!height)
  		height = 1;

  	size = ((width+3)/4)*((height+3)/4)*blockSize;

  	glCompressedTexImage2DARB(GL_TEXTURE_2D, i, format, width, height, 
  	  0, size, (char*)img->mlpData + offset);

  	offset += size;
  	
  	width >>= 1;
  	height >>= 1;

  	if(!width)
  	{
  		if(height)
  		{
  			width=1;
  			offset -= size;
  		};
  	}
  	else
  		if(!height)
  		{
  			if(width)
  				height=1;
  			offset -= size;
  		};
  }