Search code examples
c++opengltextures

Should I vertically flip the lines of an image loaded with stb_image to use in OpenGL?


I'm working on an OpenGL-powered 2d engine.

I'm using stb_image to load image data so I can create OpenGL textures. I know that the UV origin for OpenGL is bottom-left and I also intend to work in that space for my screen-space 2d vertices i.e. I'm using glm::ortho( 0, width, 0, height, -1, 1 ), not inverting 0 and height.

You probably guessed it, my texturing is vertically flipped but I'm 100% sure that my UV are specified correctly.

So: is this caused by stbi_load's storage of pixel data? I'm currently loading PNG files only so I don't know if it would cause this problem if I was using another file format. Would it? (I can't test right now, I'm not at home).

I really want to keep the screen coords in the "standard" OpenGL space... I know I could just invert the orthogonal projection to fix it but I would really rather not.

I can see two sane options:

1- If this is caused by stbi_load storage of pixel data, I could invert it at loading time. I'm a little worried about that for performance reason and because I'm using texture arrays (glTexture3d) for sprite animations meaning I would need to invert texture tiles individually which seems painful and not a general solution.

2- I could use a texture coordinate transformation to vertically flip the UVs on the GPU (in my GLSL shaders).

A possible 3rd option would be to use glPixelStore to specify the input data... but I can't find a way to tell it that the incoming pixels are vertically flipped.

What are your recommendations for handling my problem? I figured I can't be the only one using stbi_load + OpenGL and having that problem.

Finally, my target platforms are PC, Android and iOS :)

EDIT: I answered my own question... see below.


Solution

  • I know this question's pretty old, but it's one of the first results on google when trying to solve this problem, so I thought I'd offer an updated solution.

    Sometime after this question was originally asked stb_image.h added a function called "stbi_set_flip_vertically_on_load", simply passing true to this function will cause it to output images the way OpenGL expects - thus removing the need for manual flipping/texture-coordinate flipping.

    Also, for those who don't know where to get the latest version, for whatever reason, you can find it at github being actively worked on: https://github.com/nothings/stb

    It's also worth noting that in stb_image's current implementation they flip the image pixel-by-pixel, which isn't exactly performant. This may change at a later date as they've already flagged it for optimsation. Edit: It appears that they've swapped to memcpy, which should be a good bit faster.