Jump to content

  • Log In with Google      Sign In   
  • Create Account


Loading DDS textures in OpenGL, Black Texture Showing


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
3 replies to this topic

#1 harshman_chris   Members   -  Reputation: 184

Like
0Likes
Like

Posted 16 January 2013 - 09:00 AM

I am loading DDS textures with the code below, and it works fine for square textures power of two textures, but it will not load textures that are 256*128 for example. I am not sure why that is, it should work as far as I can see. Any suggestions on this?

 

GLuint ImageUtils::loadDDS(const char * filename)
{
	Logger::getInstance()->write(StringUtils::format("Loading DDS Image %s",filename));

	unsigned char header[124];
 
	FILE *fp;
 
	/* try to open the file */
	fp = fopen(filename, "rb");
	if (fp == NULL)
	{
		Logger::getInstance()->write("Failed to load Image: could not open the file");
		return 0;
	}
 
	/* verify the type of file */
	char filecode[4];
	fread(filecode, 1, 4, fp);
	if (strncmp(filecode, "DDS ", 4) != 0) 
	{
		fclose(fp);
		Logger::getInstance()->write("Failed to load Image: not a direct draw surface file");
		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;

	/* 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;
		default:
			free(buffer);
			Logger::getInstance()->write("Failed to load Image: dds file format not supported (supported formats: DXT1, DXT3, DXT5)");
			return 0;
	}

	// Create one OpenGL texture
	GLuint textureID;
	glGenTextures(1, &textureID);
 
	// "Bind" the newly created texture : all future texture functions will modify this texture
	glBindTexture(GL_TEXTURE_2D, textureID);
	glPixelStorei(GL_UNPACK_ALIGNMENT,1);  

	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)
	{
		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;
	}

	free(buffer); 

	//Unbind the texture
	glBindTexture(GL_TEXTURE_2D, 0);

	Logger::getInstance()->write(StringUtils::format("Loaded DDS Image %s",filename));

	return textureID;
}

 

 



Sponsor:

#2 swiftcoder   Senior Moderators   -  Reputation: 9860

Like
1Likes
Like

Posted 16 January 2013 - 10:01 AM

When you reach the last few mip-maps, one of width or height will reach zero before the other reaches one (and thus the mipmap will have zero dimension and be rendered as black).

 

You should change:

 

width  /= 2;
height /= 2;

 

To be something like this:

 

width = max(width/2, 1);
height = max(height/2, 1);

 

To ensure that neither dimension ever becomes zero.


Tristam MacDonald - Software Engineer @Amazon - [swiftcoding]


#3 harshman_chris   Members   -  Reputation: 184

Like
0Likes
Like

Posted 16 January 2013 - 10:33 AM

Thank you



#4 swiftcoder   Senior Moderators   -  Reputation: 9860

Like
1Likes
Like

Posted 16 January 2013 - 10:36 AM

I forgot to mention that you might actually want to not produce those last few mipmaps, rather than clamping their size.

 

When you reach the last few mipmaps of a square texture, it looks like this: 8x8, 4x4, 2x2, 1x1. For a rectangular texture, it looks like this: 8x4, 4x2, 2x1, 1x1. There probably isn't a whole lot of value to having both a 2x1 and a 1x1 mipmap around - in which case you can just exit the loop as soon as either dimension reaches 1.

 

(on the other hand, these higher mipmaps don't really consume any memory - at most a few bytes, so up to you)


Tristam MacDonald - Software Engineer @Amazon - [swiftcoding]





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS