GL_EXT_texture_compression_s3tc mipmaps

I’m having trouble getting mipmapping to work using GL_COMPRESSED_RGBA_S3TC_DXT1_EXT and GL_COMPRESSED_RGBA_S3TC_DXT5_EXT. Has anyone had similar problems, and if so, is this just because the extension isn’t finished yet, or has somebody actually got mipmapping to work using these extensions?

I didn’t have any problem!

What card vendor are you using (+Drivers)?

Can you send a code snippet to be more pragmatic?

Here’s where I load the .dds file …
/////////////////////////////////////
DWORD dw4cc;
GLSurface *pgls = NULL;
DDSURFACEDESC2 ddsd;

	byte *pbytes = (byte *)fl.pData;
	dw4cc = *((DWORD *)pbytes);
	pbytes += sizeof(DWORD);

	if (dw4cc != MAKEFOURCC('D','D','S',' ')) return NULL;

	memcpy(&ddsd,pbytes,sizeof(DDSURFACEDESC2));
	pbytes += sizeof(DDSURFACEDESC2);

	if (ddsd.dwSize != sizeof(DDSURFACEDESC2)) return NULL;
	
	if(ddsd.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
	{
		ASSERT(ddsd.dwFlags & DDSD_LINEARSIZE);
		u32 fmt(0);
		
		switch(ddsd.ddpfPixelFormat.dwFourCC)
		{
		case FOURCC_DXT1: fmt = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break;
		case FOURCC_DXT3: fmt = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break;
		case FOURCC_DXT5: fmt = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break;
		default: ASSERT_FAILED;
		}

		u32 w = ddsd.dwWidth;
		u32 h = ddsd.dwHeight;
		u32 nmips = min(ddsd.dwMipMapCount,(u32)last_bit(min(h,w))+1);

		pgls = new GLSurface(w,h,fmt,fmt,max(1,nmips),st_Texture);
		pgls->bCompressed = true;

		for(u32 imip = 0; imip < pgls->noMips(); imip++)
		{
			u32 size = w*h;
			if(fmt== GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) size>>=1;

			pgls->setImageData(imip,(void *)pbytes);
			
			pbytes += size;
			w>>=1;
			h>>=1;
		}

		return pgls;

//////////////////////////////////////////
… and here is the code for setImageData.

//////////////////////////////////////////
ASSERT(iTexObj);
ASSERT(imip < nMipLevels);
ASSERT(psrc);

u32 mipheight = nHeight&gt;&gt; imip;
u32 mipwidth  = nWidth &gt;&gt; imip;

glBindTexture(GL_TEXTURE_2D,iTexObj);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

// Mipmapping doesn't appear to work with texture compression,
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);

if(bCompressed)
{
	ASSERT(nGLPixelFmt == nGLClientPixelFmt);

	u32 nsize = mipheight * mipwidth;
	if( nGLPixelFmt == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ) nsize &gt;&gt;= 1;		
	GLDevice::glCompressedTexImage2DARB(GL_TEXTURE_2D,imip,nGLPixelFmt,
										mipwidth,mipheight,
										0,nsize,psrc);	
}
else
{
	glPixelStorei(GL_UNPACK_ALIGNMENT,nsrc_align);
	glTexImage2D(GL_TEXTURE_2D,		 
				imip,				 
				nGLPixelFmt,		 
				mipwidth,		     
				mipheight,			 
				0,					 
				nGLClientPixelFmt,	 
				GL_UNSIGNED_BYTE,	 
				psrc);				 
}

nMipFlags |= (1 &lt;&lt; imip);
return true;

Hi Sebastien (sorry Solomon, I will try to answer your question later !).

Have you received the Demo of my viewer ?!?

Eric

P.S. : OK Solomon, I am looking at your code, now !
P.S. 2 : Sebastien, I’m glad you found this discussion forum !

Now to Solomon : you say you could not get mipmapping to work. Do you mean that it worked if not using mip-maps ?

As Sebastien said, it would be useful if you told us which card/drivers you are using. In case you are using nVidia products, use the latest Detonator 2 (aka 5.22) available at www.nvidia.com.

Could you please give more details on what does not work ?

Best regards.

Eric

Salut Eric,
Hi Salomon,

Well I have found the error and guess what,(To Eric), there is a bug in my example!?!?!

you should correct:

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

where blockSize = 8 for DXT1 or 16 for DXT3/5.

and that fixes it. I have updated my sample demo and it should be reflected on the web site today!

-Sébastien

Hi Sebastien,

I just installed DX7 SDK to get the ddraw.h I needed to compile your demo (well, it took 214Mb on my hard drive just for ddraw.h !).

I just wanted to say that I had to change your GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB into GL_TEXTURE_IMAGE_SIZE_ARB (the first one not being defined for me).

Do you think it could be possible for nVidia developpers to include the glext.h and wglext.h they use when they release a demo ?

I did not have your wglext.h. Of course I just had to declare the types for wglSwapIntervalEXT (that I had in my C++ wrapper for OpenGL extensions) but I think some people might find it difficult if they are not used to using extensions…

Anyway, I have finally been able to run the demo properly and I am HAPPY !

That is great work : I am now going to implement that in the Modeller/Viewer !

Regards.

Eric

I’ve got the latest detonator drivers. When mipmapping is turned off, the compressed texture works fine.

I’ve isolated the problem to the stage when I’m reading in a compressed mip with either x or y less than 4. When I call glCompressedTexture2DARB on this mip level, I get a GL_INVALID_OPERATION. This is why the texture isn’t displaying (since one of the mips is invalid). So my question is this: What is the correct way to read in compressed mip levels which are not multiples of 4? (I’ve tried the obvious solution, to just not read such mips, and this didn’t fix the problem).

For instance, the 5th miplevel of a 64x32 texture would ordinarily be 4x2. Should I pass in 4,2 for width,height, or do I need to pass in (4,4) at minimum?

Assuming we are using a compressed format that uses 64 bits per 4x4 texel block, should the size of that miplevel be (4*2)>>1 = 4, or does it need to be at minimum the size a of 4x4 texel block = 8?