Jump to content
  • Advertisement
Sign in to follow this  
Jan Harms

Problem loading compressed DDS without pre-generated mipmaps

This topic is 2086 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi everyone, 

 

I am currently working at rendering bitmap fonts. For that I want to load dds textures. Now the program I use creates these dds files without any mipmaps, but the dds-loader I used before for some model textures seems to only work with pre-generated mipmaps.  

 

This is my loader:

 

 

 

    //    structures for reading and information variables
    char magic[4];
    unsigned char header[124];
    unsigned int width, height, linearSize, mipMapCount, fourCC;
    unsigned char* dataBuffer;
    unsigned int bufferSize;


    fstream file(path, ios::in|ios::binary);


    //    read magic and header
    if (!file.read((char*)magic, sizeof(magic))){
        cerr<< "File " << path << " not found!"<<endl;
        return false;
    }


    if (magic[0]!='D' || magic[1]!='D' || magic[2]!='S' || magic[3]!=' '){
        cerr<< "File does not comply with dds file format!"<<endl;
        return false;
    }


    if (!file.read((char*)header, sizeof(header))){
        cerr<< "Not able to read file information!"<<endl;
        return false;
    }


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


    //    determine dataBuffer size
    bufferSize = mipMapCount > 1 ? linearSize * 2 : linearSize;
    dataBuffer = new unsigned char [bufferSize*2];


    //    read data and close file
    if (file.read((char*)dataBuffer, bufferSize/1.5))
        cout<<"Loading texture "<<path<<" successful"<<endl;
    else{
        cerr<<"Data of file "<<path<<" corrupted"<<endl;
        return false;
    }


    file.close();


    //    check pixel format
    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:
        cerr << "Compression type not supported or corrupted!" << endl;
        return false;
    }


    glGenTextures(1, &ID);


    glBindTexture(GL_TEXTURE_2D, ID);
    glPixelStorei(GL_UNPACK_ALIGNMENT,1);
    //glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAX_LEVEL,0);


    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, dataBuffer + offset);


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




    textureType = DDS_TEXTURE;


    return true;
 

Now if there are no mipmaps, mipMapCount is equal to 0, and the loop does not start. I tried to set the glTexParameter and increased mipMapCount manually, but didn't really work(it showed only the "d" of "Hello World!" for some reason XD). So I'm kinda stuck now. 

 

I think somewhere I have to manually create the mipmaps with glGenerateMipmap but I'm not sure where and in what why the loop still works then.

 

I hope someone can help me out here. 
 

Thanks in advance. 

Share this post


Link to post
Share on other sites
Advertisement

Well, glCompressedTexImage2D has to get called one way or another.  Try this:

 

for (unsigned int level = 0; level < (mipMapCount+1) && (width || height); ++level) {

 

This way, the top level mipmap level always gets set.  Textures that don't use/need mipmaps still need level 0 accounted for.  It appears that you were setting every mip level except for the last.  Keep in mind that the mipMapCount represents the mipmap levels "besides" the top level, which is always 0.  Try this and make sure it works. ^^

 

Shogun.

Share this post


Link to post
Share on other sites

Thanks for your answer. 

 

Well this kind of works. Somehow only a few of my chars get drawn then, others are just invisible/(black if no transparency) so the texture is not loaded correctly there. 

Share this post


Link to post
Share on other sites

Okay I solved it. 

 

In case the texture had no pre-generated mipmaps, the data was only read partly because the bufferSize was devided by 1.5, which is needed for the case with mipmaps.

The solution was therefore to replace this code

 

 

 

//    determine dataBuffer size
    bufferSize = mipMapCount > 1 ? linearSize * 2 : linearSize;
    dataBuffer = new unsigned char [bufferSize*2];


    //    read data and close file
    if (file.read((char*)dataBuffer, bufferSize/1.5))
        cout<<"Loading texture "<<path<<" successful"<<endl;
 

by this code

 

 

 

//    determine dataBuffer size
    bufferSize = mipMapCount > 1 ? linearSize * 2 : linearSize * 1.5;
    dataBuffer = new unsigned char [bufferSize*2];


    //    read data and close file
    if (file.read((char*)dataBuffer, bufferSize/1.5))
        cout<<"Loading texture "<<path<<" successful"<<endl;
 

Thanks for your help.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!