3

I have a function to load a texture from a JPEG image using SOIL.

So far I have been loading the texture with the SOIL_load_image() function and then supplying the image to OpenGL using glTexImage2D (see code below). However! My textures is upside down, so I wanted to use the SOIL_load_OGL_texture() instead and supply the SOIL_FLAG_INVERT_Y in order to flip the images. My problem is though, that I get an unhandled exception at the SOIL_load_OGL_texture() function.

The code is almost a copy paste from the documentation, so I don’t understand why this error occurs?

(NOTE: I could invert the textures in my vertex shader, but I would like to use SOIL.)

The old way

int width;
int height;

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures[0]);

image = SOIL_load_image(filename, &width, &height, 0, SOIL_LOAD_RGB);

if (image == NULL) {
    std::cout << "An error occurred while loading image." << std::endl;
    exit(EXIT_FAILURE);
}
std::cout << "Loaded first texture image" << std::endl;

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

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

What I am trying now

GLuint image;

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures[0]);

image = SOIL_load_OGL_texture(
        filename,
        SOIL_LOAD_RGB,
        SOIL_CREATE_NEW_ID,
        SOIL_FLAG_INVERT_Y
    );

if (image == 0)
    cerr << "SOIL loading error: '" << SOIL_last_result() << "' (" << "res_texture.png" << ")" << endl;

And the error

Unhandled exception at 0x0F5427FF (msvcr110d.dll) in AnotherTutorial.exe: 0xC0000005: Access violation reading location 0x00000000.
Palec
  • 12,743
  • 8
  • 69
  • 138
Købmanden
  • 117
  • 1
  • 2
  • 10
  • In the `SOIL_load_OGL_texture()` version why are you (apparently) throwing away the new texture object (`image`)? – genpfault Jun 04 '13 at 21:28
  • How am I throwing it away? With the SOIL_CREATE_NEW_ID flag, or? – Købmanden Jun 04 '13 at 21:41
  • Well, you don't seem to be assigning `image` to `textures[0]` or `glBindTexture()`ing it. – genpfault Jun 04 '13 at 21:58
  • Why do you need the `glBindTexture(GL_TEXTURE_2D, textures[0])` before the image loading? – Grimmy Jun 04 '13 at 22:13
  • @genpfault Perhaps I don't completely understand the SOIL_load_OGL_texture; I thought that it loaded a texture directly into OpenGL, and I therefore did not need to call something like glTexImage2D? – Købmanden Jun 05 '13 at 08:03
  • @Grimmy I load three images in total, so I call the function three times (textures[0], textures[1], textures[2]). – Købmanden Jun 05 '13 at 08:04

5 Answers5

1

Seems like there is no answer to using SOIL, so i'll post my solution:

In the vertex shader I do:

Texcoord = vec2(texcoord.x, 1.0-texcoord.y);
gl_Position = proj * view * model * vec4( position, 1.0 );

The 1.0-texcoord.y inverts the y-axis of the image. Not as clean a solution, but it works.

Købmanden
  • 117
  • 1
  • 2
  • 10
  • 1
    I thought you're having a problem with the RT error occurring not flipping upside down the texture? – mr5 Sep 30 '13 at 13:04
1
void loadTexture(GLuint* texture, char* path){
    *texture = SOIL_load_OGL_texture(filename,
                                     SOIL_LOAD_AUTO,
                                     SOIL_CREATE_NEW_ID,
                                     SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_MULTIPLY_ALPHA
                                    );
    if(*textre == NULL){
        printf("[Texture loader] \"%s\" failed to load!\n", filename);
    }
}

void drawTexturedRect(int x, int y, int w, int h, GLuint texture){
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, texture);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glDepthMask(GL_FALSE);
    glDisable(GL_DEPTH_TEST);
    glBegin(GL_QUADS);
        glColor3f(255,255,255);
        glTexCoord2f(0,0);
        glVertex2f(x,y);
        glTexCoord2f(1,0);
        glVertex2f(x+w,y);
        glTexCoord2f(0,1);
        glVertex2f(x,y+h);
        glTexCoord2f(1,1);
        glVertex2f(x+w,y+h);
        glTexCoord2f(0,1);
        glVertex2f(x,y+h);
    glEnd();
    glEnable(GL_DEPTH_TEST);
    glDepthMask(GL_TRUE);
    glDisable(GL_BLEND);
}

And then you can do:

// At initialization
GLuint texture;
loadTexture(&texture, "filename.png");

// Drawing part
drawTexturedRect(25,25,256,256,texture);

This is what I personally use, and it works perfectly. I'm using Visual Studio 2012 combined with SDL and SOIL.

GreySkull
  • 23
  • 4
0

SOIL_load_image will return unsigned char* yes, array holding your image data.

Then you will normally feed this data to gl using glGenerateTextures, assign texture IDs, calling glTexImage2D.

SOIL_load_OGL_texture returns a texture id, so you could do this instead:

texture[0] = SOIL_load_OGL_texture(...)

if your goal is to load textures 0,1,2.

As for invert y, the easiest and weight free solution is to flip the texture coordinates in glTexCoord, but it depends on what you are doing. If you are loading resources as a one time only operation or like, it can’t hurt, except some startup time probably not worth mentioning. But if you’re loading resources dynamically through the main loop when needed, then invert y flag (and about any flag), can hurt performance because of additional processing throughout your entire program.

One big advantage to using SOIL_load_image is that you can retrieve width, height and channel number from the original image which SOIL_load_OGL_texture doesn’t provide.

If it helps, SOIL_load_OGL_texture would crash after a while when loading RGB images as RGB but worked fine all the way with SOIL_LOAD_RGBA, that could be a fix to your problem.

I still find it easier with SOIL_load_image. I hope any of this helps. Also check the SOIL source code that ships with soil to see what’s going on.

xpet
  • 1
  • 2
  • Welcome to SO! Please use capital letters at sentence start and Markdown formatting for function names and other code snippets. This greatly improves the readability of the text. See [editing help](http://stackoverflow.com/editing-help). – Palec Dec 27 '13 at 02:34
0

Basically, in the command

SOIL_load_image(filename, &width, &height, 0, SOIL_LOAD_RGB);

the 0 (NULL) you are passing is a pointer to the channels set by the library, so, of course, when the library tries to access it you have:

Unhandled exception at 0x0F5427FF (msvcr110d.dll) in AnotherTutorial.exe: 0xC0000005: Access violation reading location 0x00000000

Try declaring a variable and using it:

int channels;
SOIL_load_image(filename, &width, &height, &channels, SOIL_LOAD_RGB);
Patrice Gahide
  • 3,644
  • 1
  • 27
  • 37
LeDYoM
  • 949
  • 1
  • 6
  • 21
0

None of the solution above works for me. I have same problem just now, like the following one:

SOIL_load_OGL_texture Unhandled exception at xxxxxx (msvcr120d.dll)

After reading solution at http://www.idevgames.com/forums/thread-10281.html, i changed my path from "relative path" to "absolute path".

BTW, And since I am Chinese, i need to make sure that the path is ALL ENGLISH without non-ascii characters.

For example:

I change my code from

SOIL_load_OGL_texture("my_texture.bmp",
        SOIL_LOAD_AUTO,
        SOIL_CREATE_NEW_ID,
        SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_MULTIPLY_ALPHA
        );

to

SOIL_load_OGL_texture("D:\temp_20160926\ConsoleApplication20\ConsoleApplication19\my_texture.bmp",
        SOIL_LOAD_AUTO,
        SOIL_CREATE_NEW_ID,
        SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_MULTIPLY_ALPHA
        );

And it solve my problem perfectly.

I think this is a bug/restriction in SOIL. But you can avoid this by specific the absolute path like i do here.

Hope it can help you too.

Divyang Desai
  • 7,483
  • 13
  • 50
  • 76