I’m trying to load some DXT1 compressed textures into a cube map array, and running into a couple errors. I’m using opengl 4.5. The code to read in the files was is based off of this tutorial, and I think it’s working correctly. The results all have consistent height, width, and size. Also, in case it matters, the images do have mipmaps.
My first issue is that glCompressedTexImage3D is giving me an INVALID_VALUE. From the documentation, I think that has to mean my imageSize is invalid. But I’m reading it directly from the the image files as they are loaded. I’m not sure how else I’m supposed to get it.
The second error is INVALID_OPERATION, in glCompressedTexSubImage3D. The docs have a couple things that can cause this, but I’m guessing it’s this one:
GL_INVALID_OPERATION is generated if parameter combinations are not supported by the specific compressed internal format as specified in the specific texture compression extension.
But I’m not really sure what that means, or how to fix it. My format in this case is GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, but I’ve tried using more general ones, like GL_COMPRESSED_RGBA. No luck.
void Visual::LoadTextures()
{
std::vector<std::string> faces;
for (int i = 0; i < imguiStatus.textureFolders.size(); i++) {
std::string folder = imguiStatus.textureFolders[i];
faces.push_back("../cubemaps/" + folder + "/right_PNG_DXT1_1.dds");
faces.push_back("../cubemaps/" + folder + "/left_PNG_DXT1_1.dds");
faces.push_back("../cubemaps/" + folder + "/top_PNG_DXT1_1.dds");
faces.push_back("../cubemaps/" + folder + "/bottom_PNG_DXT1_1.dds");
faces.push_back("../cubemaps/" + folder + "/back_PNG_DXT1_1.dds");
faces.push_back("../cubemaps/" + folder + "/front_PNG_DXT1_1.dds");
}
glGenTextures(1, &cubemap);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, cubemap);
int width, height, mipmapCount, format, imageSize;
unsigned char * image;
for (GLuint i = 0; i < faces.size(); i++)
{
image = LoadDDS(faces[i], &format, &mipmapCount, &width, &height, &imageSize);
// format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT in my case
if (i == 0) {
glCompressedTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY,
0, // level
format, // Internal format
width, height, faces.size(), // width,height,depth
0, //border
faces.size() * imageSize, // imageSize
0); // pointer to data
GetGlError();
}
unsigned int blockSize = (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16;
unsigned int offset = 0;
/* load the mipmaps */
for (unsigned int level = 0; level < mipmapCount && (width || height); ++level)
{
int size = ((width + 3) / 4)*((height + 3) / 4)*blockSize;
glCompressedTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, level, 0, 0, i, width, height, 1, format, size, image + offset);
GetGlError();
offset += size;
width /= 2;
height /= 2;
}
free(image);
}
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
}
//http://www.opengl-tutorial.org/beginners-tutorials/tutorial-5-a-textured-cube/
#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
unsigned char * Visual::LoadDDS(std::string imagepath, int * format, int * mipmapCount, int * width, int * height, int * imageSize)
{
unsigned char header[124];
FILE *fp;
/* try to open the file */
fopen_s(&fp, imagepath.c_str(), "rb");
if (fp == NULL)
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);
*height = *(unsigned int*)&(header[8]);
*width = *(unsigned int*)&(header[12]);
*mipmapCount = *(unsigned int*)&(header[24]);
unsigned int linearSize = *(unsigned int*)&(header[16]);
unsigned int fourCC = *(unsigned int*)&(header[80]);
unsigned char * buffer;
/* how big is it going to be including all mipmaps? */
*imageSize = *mipmapCount > 1 ? linearSize * 2 : linearSize;
buffer = (unsigned char*)malloc(*imageSize * sizeof(unsigned char));
fread(buffer, 1, *imageSize, fp);
/* close the file pointer */
fclose(fp);
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;
default:
free(buffer);
return 0;
}
return buffer;
}
Any help is much appreciated!