Search code examples
c++opengltextures

Exception thrown at 0x69ABF340 when loading image with STBI_Image OpenGL


I'm trying to load a .jpg image as a background, I loaded it with stbi_load however when i try to draw the texture i get the following error: Exception thrown at 0x69ABF340 (nvoglv32.dll) 0xC0000005: Access violation reading location 0x0C933000. occurred

I tried changing the channels while loading the image, perhaps the image is not in rgb but rgba, with no success.

int width = 1280;
    int height = 720;
    int channels = 3;
    GLuint t;
    stbi_set_flip_vertically_on_load(true);
    unsigned char *image = stbi_load("bg.jpg",
        &width,
        &height,
        &channels,
        STBI_rgb);
    glEnable(GL_TEXTURE_2D);
    glGenTextures(1, &t);

    glBindTexture(GL_TEXTURE_2D, t);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);

    glBindTexture(GL_TEXTURE_2D, 0);

The window should contain the texture specified, instead I get a white window with an exception.


Solution

  • The parameter STBI_rgb indicates to load an generate a texture with 3 color channels. This causes that the image buffer (image) consists of 3 bytes per pixel.

    But when you specify the two-dimensional texture image by glTexImage2D then the specified format is GL_RGBA, which suggests 4 channels and so 4 bytes per pixel.
    This causes that the data buffer is read out of bounds. Change the format parameter to GL_RGB, to solve that.

    Further note, that by default OpenGL assumes that the start of each row of an image is aligned 4 bytes. This is because the GL_UNPACK_ALIGNMENT parameter by default is 4. Since the image has 3 color channel, and is tightly packed the start of a row is possibly misaligned.
    Change the the GL_UNPACK_ALIGNMENT parameter to 1, before specifying the two-dimensional texture image (glTexImage2D).

    Further more, the texture is not (mipmap) complete. The initial value of GL_TEXTURE_MIN_FILTER is GL_NEAREST_MIPMAP_LINEAR. If you don't change it and you don't create mipmaps, then the texture is not "complete" and will not be "shown". See glTexParameter.
    Either set the minification filter to GL_NEAREST or GL_LINEAR

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    

    or generate mipmaps by glGenerateMipmap(GL_TEXTURE_2D) to solve the issue.

    e.g.:

    glBindTexture(GL_TEXTURE_2D, t);
    
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);