Pregunta

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.
¿Fue útil?

Solución

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.

Otros consejos

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.

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.

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);

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top