Texture compression and/or lower image quality in code

Hello! I’m learning OpenGL and I have these big textures I’m loading onto a model. When I run my application I see that I’m using ~500MB for texture files that are ~30MB on disk…

What I need your help with is texture compression, how do I compress a 2D texture and use it?
Another idea I had was to lower the image quality the further away you are. Is there some way to lower the image quality in code?

I’m using OpenGL 3.3 with glfw, glad to load the OpenGL functions and stb_image.h to load the actual image.

This is how I am currently loading images:

How I am loading images
unsigned int TextureFromFile(const char* path, const std::string& directory, bool gamma)
{
    std::string filename = std::string(path);
    filename = directory + '/' + filename;

    unsigned int textureID;
    glGenTextures(1, &textureID);

    int width, height, nrComponents;
    unsigned char* data = stbi_load(filename.c_str(), &width, &height, &nrComponents, 0);
    if (data)
    {
        GLenum format;
        if (nrComponents == 1)
            format = GL_RED;
        else if (nrComponents == 3)
            format = GL_RGB;
        else if (nrComponents == 4)
            format = GL_RGBA;

        glBindTexture(GL_TEXTURE_2D, textureID);
        glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
        glGenerateMipmap(GL_TEXTURE_2D);

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

        stbi_image_free(data);
    }
    else
    {
        std::cout << "Texture failed to load at path: " << path << std::endl;
        stbi_image_free(data);
    }

    return textureID;
}

How are you measuring this memory consumption? I’ll note that just because the driver has allocated 500 MB of GPU memory does not mean all if it is in use, it may just allocate GPU memory in large chunks and use it for textures/buffers as needed.

I’m not sure if you are asking how to use compressed texture formats or how to get the compressed image data.

For the former see OpenGL Wiki: Compressed Texture Formats.

For the latter there are tools, e.g. from the big GPU vendors AMD Compressonator, Nvidia NVTT3, or crunch.

1 Like

How are you measuring this memory consumption?

Visual Studio 2022 has a tool that shows the process memory, I assumed it was the ram usage but maybe it is also GPU memory? I’m worried that if I load a few more textures and I use 8GB of “process” memory it would use up all the ram on my computer, but if it shows the GPU memory as well then I should be fine to load many many textures?
How can I tell how much ram and gpu ram I am using separately?

I’m not sure if you are asking how to use compressed texture formats or how to get the compressed image data.

I thought the process was you load the texture, then you compress it in the code, and then send it off to the GPU or wherever. Turns out I was wrong! Thank you for the resources so I can compress textures and load them, hopefully I’ll be able to get them working.

I’m not sure if this is possible but can you resize a texture in code? Is there some fancy function to do so? I originally half-asked how to lower image quality but I meant to say if it is possible to resize a texture. The reason why I would like this is because the textures I have are 4096 x 4096 pixels and I don’t have a 4k monitor so many of those pixels are not going to show. It would probably be better to store them as 1080 x 1080. First of all, yes I know I can just resize the image with mspaint and then load the textures, but it would be nice to have the option for texture quality.

Have you actually done the math on the size of that data? It’s pretty simple math.

A 4096x4096 texture contains 16’777’216 pixels. At 4 bytes per pixel, that’s an even 64MiB. And that’s just for the base mipmap layer. A full mipmap pyramid for a 2D texture costs approximately 1.33x the cost of the base layer, so that’s 85.12MiB per texture.

You’ll probably get more visual quality out of texture compression than resizing. You’d have to drop to 2048x1024 in size (a factor of 8x smaller) to get the same data storage size as a 4096x4096 DXT1 compressed texture (which is 4-bits-per-pixel, though no usable alpha channel).

1 Like