How to load BC7 (BPTC) Texture?

I need ‘compressed texture’ in our project.

I try for DXT1~5, ASTC and get some result.
then now i want try BPTC format(BC7), but i cant find BC7 loader anyware!

I get BC7 texture with Compressonator, I open it for vs2019, format is DXGI_FORMAT_BC7_UNORM.
it’s not same to GL_COMPRESSED_RGBA_BPTC_UNORM ?

I have DXT loader, but it’s not work with BC7. result is so…crazy.
left is original, right is BC7.

lower is my DDS file loader.

#define FOURCC_DXT1 0x31545844 // Equivalent to "DXT1" in ASCII
#define FOURCC_DXT3 0x33545844 // Equivalent to "DXT3" in ASCII
#define FOURCC_DXT5 0x35545844 // Equivalent to "DXT5" in ASCII
#define FOURCC_BPTC 0x30315844
float loadDDS(const char * imagepath) {

unsigned char header[124];

FILE *fp;

/* try to open the file */
fp = fopen(imagepath, "rb");
if (fp == NULL) {
	printf("%s could not be opened. Are you in the right directory ? Don't forget to read the FAQ !\n", imagepath); getchar();
	return 0;
}

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

/* get the surface desc */
fread(&header, 124, 1, fp);

unsigned int height = *(unsigned int*)&(header[8]);
unsigned int width = *(unsigned int*)&(header[12]);
unsigned int linearSize = *(unsigned int*)&(header[16]);
unsigned int mipMapCount = *(unsigned int*)&(header[24]);
unsigned int fourCC = *(unsigned int*)&(header[80]);

unsigned char * buffer;
unsigned int bufsize;
if (fourCC == FOURCC_BPTC) {//in BC7 header, linearSize is small(8192), width/height is 2048.
	linearSize = height * width;
	bufsize = mipMapCount > 1 ? linearSize * 2 : linearSize;
	buffer = (unsigned char*)malloc(bufsize * sizeof(unsigned char));
	fread(buffer, 1, bufsize, fp);
}
else {
	/* how big is it going to be including all mipmaps? */
	bufsize = mipMapCount > 1 ? linearSize * 2 : linearSize;
	buffer = (unsigned char*)malloc(bufsize * sizeof(unsigned char));
	fread(buffer, 1, bufsize, fp);
}
/* close the file pointer */
fclose(fp);

unsigned int components = (fourCC == FOURCC_DXT1) ? 3 : 4;
unsigned int format;
switch (fourCC)
{
case FOURCC_DXT1:
	format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
	break;
case FOURCC_DXT3:
	format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
	break;
case FOURCC_DXT5:
	format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
	break;
case FOURCC_BPTC:
	format = GL_COMPRESSED_RGBA_BPTC_UNORM;
	//format = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM;	
	//format = GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT;
	//format = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT;
	break;
default:
	free(buffer);
	return 0;
}

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

unsigned int blockSize = (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16;
unsigned int offset = 0;

float compute_time;
glFinish();
CHECK_TIME_START;

/* load the mipmaps */
for (unsigned int level = 0; level < mipMapCount && (width || height); ++level)
{
	unsigned int size = ((width + 3) / 4)*((height + 3) / 4)*blockSize;
	glCompressedTexImage2D(GL_TEXTURE_2D, level, format, width, height, 0, size, buffer + offset);

	offset += size;
	width /= 2;
	height /= 2;

	// Deal with Non-Power-Of-Two textures. This code is not included in the webpage to reduce clutter.
	if (width < 1) width = 1;
	if (height < 1) height = 1;

}
glFinish();
CHECK_TIME_END(compute_time);

free(buffer);

return compute_time;

}

please help me!

KTX and KTX2 are very, very close to OpenGL and support storing textures in pretty much any format you can possible represent in OpenGL (compressed and uncompressed internal formats, texture arrays, etc.).

Consider using a tool or library that converts to KTX/KTX2, and then just load that into OpenGL. Here are a few links that have links to some of these tools and libraries:

In fact, Basis is built on KTX2 and supports real-time transcode from its super-compressed format to various desktop and mobile GPU compressed texture formats, including BC7.

thank for your help.
i try that, Compressonator (AMD compress tool) support .ktx and using ktx loader(from opengl superbible) …
but it works same. crazy result again.

Compressonator has error…? or superbible is wrong book? i’m so confussing…

Post a short, stand-alone GLUT or GLEW-based test program that illustrates your problem.

With this, we can scan your GL usage and help you spot problems. Also, we can download, compile, and run your test program to help you figure out what’s missing in your code.

Just scanning your code snippet above (the loadDDS() function), I don’t see any creation of a texture handle nor binding that texture handle. So I assume you’re calling this before calling this function (?)

Again, posting the full source for a self-contained test program would clear up a lot of potential issues.

I try to make small, but it’s little big to upload whole code here.
please build with x86, not x64.

program load BC7 file and display it. it look’s so bad…
i’m so thanks to your help.

You don’t need to use a KTX container for this to work, DDS will work fine for your example.

I think the reason for why your are seeing the noisy image is not because of OpenGL, but because you are parsing your DDS wrong.

Iirc the DDS spec is like this:
FILE_INFO [4]
HEADER [124]
*DX10_HEADER[20] (only exists in DX10)

If you are using DXT3 you don’t have the DX10 header and therefore your texture data will start at index 128(4+124). If you are in fact using DX10 your *DX10_HEADER takes up 20 additional bytes and your texture data will start at index 148(4+124+20).

Iirc using COMPRESSED_RGBA_BPTC_UNORM should be the way to go.