DXTC image uploading issues

Hello,

I have two problem which are related to loading DDS files as textures.

First, DDS is a DirectX format whose image origin is top-left. When trying to upload such an image into OpenGL, the image is flipped. Can anything be done about that whitout touching the texture coordinates? Is it possible to vertically “flip” the DXTC image data in compressed form?

Second problem is when trying to use NPOT+DXTC. The s3tc specs say:

  1. How does this extension interact with specific texture compression
    extensions such as EXT_texture_compression_s3tc?
  STATUS: RESOLVED
  RESOLUTION:  It does not.  If both this extension and
  EXT_texture_compression_s3tc are supported, applications can safely
  load NPOT S3TC-compressed textures. 

But when trying to actually make use of this, I get GL errors. I have to make the textures power-of-two first. Has anyone experienced the same?

I don’t know well the dds format, but did you try to flip vertically your picture data array? I mean maybe you could copy data in a new array reading the first from bottom to top…

http://en.wikipedia.org/wiki/S3TC
It’s blocks of 4x4 pixels, each block having a color-data “header”.
You’ll need to flip all rows of blocks, and also flip that table in each block.

Here’s how I think you’ll swap DXT1:


void DXT1_SwapVertically(int* data,int wid=256,int hei=128){

	int rowsize=wid*2; // in dwords
	int *ptr1=data; // first row
	int *ptr2=data+(rowsize*(hei-1)); // last row

	for(int y=hei/8;y--;){ // this loop flips blocks vertically
		for(int x=rowsize;x--;){
			int temp = *ptr1;
			*ptr1 = *ptr2;
			*ptr2 = temp;
			ptr1++;
			ptr2++;
		}
		ptr2-=2*rowsize;
	}

	#define DXT_IS_COLOR_FIRST 1 // I am not sure which it is

	#if DXT_IS_COLOR_FIRST
		char* ptr3=(char*)(data+1);
	#else
		char* ptr3=(char*)data;
	#endif
	for(int b=hei*rowsize;b--;){ // for each block
		// this whole thing can be done easily with "bswap" in inline asm
		char temp2;
		temp2 = ptr3[0];
		ptr3[0]=ptr3[3];
		ptr3[3]=temp;
		
		temp2 = ptr3[1];
		ptr3[1]=ptr3[2];
		ptr3[2]=temp;
		
		ptr3+=8;
	}

}

Ah, some errata:
for(int b=heirowsize;b–;){ // for each block
should be replaced with
for(int b=wid
hei/16;b–;){ // for each block

better use the texture matrix for flipping, something like this should do the trick:
1 0 0 0
0 -1 0 1
0 0 1 0
0 0 0 1

Actually you should not have to flip at all. While OpenGL defines the texture origin as bottom-left (which is a rather meaningless statement for texture space as it has no orientation), it also defines that texture data is uploaded in bottom-to-top order.

EXT_texture_compression_s3tc also defines the block and texel positions this way, so that the first block (the one at the lowest address in memory) is always at the origin of texture space.

Ok, I tried to flip the DXTC data line by line(leaving the blocks itself intact). This didn’t help completely…it really seems I have to flip the blocks internally, too.

There’s some code included in the NV SDK to flip DXT compressed images without de- & re-compressing them. If you just want the relevant snippets (nv_dds.cpp):

http://www.google.com/search?hl=en&q=nv_dds.cpp&btnG=Google+Search

Make sure you have the latest (beta) drivers, there was a bug in the 169.21 ForceWare drivers that corrupted DXT1 mipmaps, and possibly other issues.

http://www.opengl.org/discussion_boards/…true#Post236337

There’s some code included in the NV SDK to flip DXT compressed images without de- & re-compressing them. If you just want the relevant snippets (nv_dds.cpp)

Thanks, this is exactly what I needed.

Update: I got vertical flipping and uploading NPOT-DTXn-Textures working.

When uploading NPOT-DXTn data, you need to calculate the imageSize parameter of glCompressedTexImage2DARB as if you would round both ‘width’ and ‘height’ up to the next divisible-by-4 values. The same is true to get from one mipmap-image to the next inside the DDS file.

And this surprises you? DXTn works (only!) on 4x4 blocks.

You might want to have a look at
http://msdn.microsoft.com/en-us/library/bb206238(VS.85).aspx