Search code examples
c++imageopenglresourcessoil

How to embed any *.jpg image inside win32 executable and use it at run time


I am doing a project in pure OpenGL and FREEGLUT named Space Voyager. Problem is that during run time when programe calls a function to load all the images player has to wait around 2 minutes on loading screen!!!! Some of the images are like 16 MB files otherwise 1 MB in average. There are like 20 images in all. I need to load all the images before staring the level.

Now I am using SOIL for loading the images in my game. SOIL has a function to load images from memory SOIL_load_OGL_texture_load_from_memory( unsigned char *image_in_RAM ,...).

My solution is to embed all the images in *.exe file of the game and use it at run time so as to save the time to load all the images in game.

I am pretty much lost as how to exactly embed the jpg images in executable and
use it at run time as unsigned char* imagePointer ?????


Solution

  • My solution is to embed all the images in *.exe file of the game and use it at run time so as to save the time to load all the images in game.

    How do you suppose this would do the trick? It doesn't matter what label the data on the storage device has on it. The effort for the computer system are invariant. It doesn't matter if you place the resources in a separate file to the computer it makes no difference whatsoever.

    Some of the images are like 16 MB files otherwise 1 MB in average. There are like 20 images in all. I need to load all the images before staring the level.

    That's not a lot of data. 20 images with 1MiB in average, that's 20MiB in average. Even slow HDD disks of spinning rust can deliver 10MiB/s easily. A much more common figure is something like 50MiB to 80MiB/s for cheap HDDs these days. Wherever your bottleneck lies, it's not I/O.

    Also keep in mind that if you embedded the files RAW into the executable you're forcing the system to shove more data through I/O; having the images compressed in the executable still requires you to decompress. Given the fact that most of the time you're I/O bound and not CPU bound having compressed images in storage is desireable.

    UPDATE

    Your problem is this:

    SOIL_FLAG_POWER_OF_TWO

    You're asking soil to rescale each and every image to the next bigger size that's a power of 2. Before OpenGL-2 this had to be done, since OpenGL-1 would only accept power-of-2 sized images for textures. Ever since OpenGL-2 came out (and you'll be hard pressed to find a GPU that doesn't support OpenGL-2 these days), that constraint has been lifted.

    Another time consuming operation is the generation of mipmaps (SOIL_FLAG_MIPMAPS) since this required the generation of a whole image pyramid for each image. Now mipmapping is something you generally want to have. In case you have a context >=OpenGL-3 you can use the OpenGL built in mipmap generator. Also you're asking SOIL to generate texture IDs for you, but you also generate IDs yourself. Use either one, but don't use both.

    This leads to the following suggested changes in your code:

    while( GL_NO_ERROR != glGetError() ); // flush OpenGL errors;
    GLint gl_version;
    glGetIntegerv(GL_MAJOR_VERSION, &gl_version);
    if( GL_NO_ERROR != glGetError() ) {
        // GL_MAJOR_VERSION enum supported only since OpenGL-3
        gl_version = 1;
        while( GL_NO_ERROR != glGetError() ); // flush OpenGL errors;
    }
    bool const gl3_or_later = 3 <= gl_version;
    
    tex_id = SOIL_load_OGL_texture(
            fileNameConstant,
            SOIL_LOAD_AUTO,
            SOIL_CREATE_NEW_ID,
            gl3_or_later ? 0 : SOIL_FLAG_MIPMAPS );
    if( gl3_or_later ) {
        glBindTexture(GL_TEXTURE_2D, tex_id);
        glGenerateTextureMipmap(GL_TEXTURE_2D);
        glTexParameteri(
            GL_TEXTURE_2D,
            GL_TEXTURE_MIN_FILTER,
            GL_LINEAR_MIPMAP_LINEAR);
        glTexParameteri(
            GL_TEXTURE_2D,
            GL_TEXTURE_MAX_LEVEL,
            1000);
    }