SFML community forums

Help => Graphics => Topic started by: Tabasco on May 25, 2009, 07:34:47 pm

Title: upside-down textures in OpenGL
Post by: Tabasco on May 25, 2009, 07:34:47 pm
I've been moving one of my projects from GLFW to SFML.  The transition has been relatively simple, but with SFML when I load my models the textures are upside-down.

I have some models that I've made and UV-mapped in blender as well as some procedurally generated terrain meshes and the behavior has been the same.  I've tried storing the textures as jpg and png instead of tga, but as of yet, the only way I can get it looking right is to go into gimp and mirror the image.

This is what I'm getting:
The textures, original and flipped: http://tyranny.ckt.net/tabasco/kilntex.jpg

The results:
http://tyranny.ckt.net/tabasco/kiln1.jpg
http://tyranny.ckt.net/tabasco/kiln2.jpg

(I'm not particularly artistic, but there it is)

I'm loading textures almost exactly like I did in GLFW and SDL before that.  There are only a few minor differences:

Code: [Select]

    sf::Image Image;

    if (!Image.LoadFromFile(texname)) { return(0); }

    glGenTextures(1, &texid);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    glBindTexture(GL_TEXTURE_2D, texid);

    gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, Image.GetWidth(), Image.GetHeight(), GL_RGBA, GL_UNSIGNED_BYTE, Image.GetPixelsPtr());


I've compiled it in Windows XP and Ubuntu 9.04 with no visible difference.
Any ideas?
Title: upside-down textures in OpenGL
Post by: Tabasco on May 25, 2009, 08:22:21 pm
Just to be thorough, I made some adjustments to the OpenGL demo program bundled with SFML1.4.

The rotation has been removed and all of the quads but one have been commented out.

Code: [Select]

glTexCoord2f(0, 0); glVertex3f(-50.f, -50.f, 50.f);
glTexCoord2f(0, 1); glVertex3f(-50.f,  50.f, 50.f);
glTexCoord2f(1, 1); glVertex3f( 50.f,  50.f, 50.f);
glTexCoord2f(1, 0); glVertex3f( 50.f, -50.f, 50.f);


http://tyranny.ckt.net/tabasco/smile.jpg
Title: upside-down textures in OpenGL
Post by: Laurent on May 25, 2009, 09:55:26 pm
The OpenGL demo uses a perspective projection with the Y axis pointing upwards. The result is just as expected.
Title: upside-down textures in OpenGL
Post by: Tabasco on May 25, 2009, 10:27:31 pm
Quote from: "Laurent"
The OpenGL demo uses a perspective projection with the Y axis pointing upwards. The result is just as expected.


If it's the projection, wouldn't all of my geometry be upside-down as well, not just the texture assignment?
Based on how opengl views texture coordinates
( http://www.gamedev.net/reference/programming/features/ogltm/texcoord.jpg )
the texture should not be upside-down on the above quad.
The quad starts in the lower left corner, then the upper left, moving clockwise and the texture coordinate provided for the bottom corner of the quad would correlate to the bottom corner of the texture image.

After a little more reading I came across this:
http://www.devolution.com/pipermail/sdl/2005-February/067479.html

If the data provided by sf::Image uses a top-left origin, it would be upside down in OpenGL.
Title: upside-down textures in OpenGL
Post by: Laurent on May 25, 2009, 11:36:31 pm
Quote
Based on how opengl views texture coordinates
( http://www.gamedev.net/reference/programming/features/ogltm/texcoord.jpg )
the texture should not be upside-down on the above quad.

This picture confuses me. I've always thought the origin for texture mapping was the top-left corner. And I never got flipped textures so far.

Unfortunately I can't find any reliable source other than this tutorial.
Title: upside-down textures in OpenGL
Post by: Imbue on May 26, 2009, 12:27:53 am
I think that texture coordinates go with the geometry coordinates. So if your geometry has the Y axis pointing down, your texture coordinates should too.
Title: upside-down textures in OpenGL
Post by: Tabasco on May 26, 2009, 12:45:16 am
I'm surprised this isn't explained better than it is.  So far the best I've found is point 12 here:
http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall/

Quote
Another common pitfall related to 2D rendering APIs having an upper left-hand coordinate system is that 2D image file formats start the image at the top scan line, not the bottom scan line. OpenGL assumes images start at the bottom scan line by default.


The NeHe tutorials and other implementations I've found scattered across the Internet all flip the image so that the origin is at the lower-left corner as well, but they don't explain why.  :(

I guess my question now is, what's the fastest way to swap the row order in an sf::Image?
Title: upside-down textures in OpenGL
Post by: Laurent on May 26, 2009, 07:48:54 am
Quote
I guess my question now is, what's the fastest way to swap the row order in an sf::Image?

You can't do it with sf::Image. The best solution is to do iy yourself, using GetPixelsPtr() and a temporary array to hold the flipped pixels.

However I'm going to look into this, maybe I can fix it directly in SFML.
Title: upside-down textures in OpenGL
Post by: Tabasco on May 28, 2009, 12:57:07 am
Thanks!  I appreciate that you're really active on this project and I'm looking forward to seeing how it grows.

In the mean time I'm just flipping rows like this

Code: [Select]

    GLuint imgsize = (Image.GetWidth() * Image.GetHeight()) * 4;
    GLuint rowsize = Image.GetWidth() * 4;
    sf::Uint8 *newimg = (sf::Uint8*) malloc(imgsize+1);
    const sf::Uint8 *oimg = Image.GetPixelsPtr();

    GLuint x;
    for(x = 0; x < Image.GetHeight(); x++)
    {
        memcpy(newimg + (x * rowsize), (oimg + imgsize) - (rowsize + (rowsize * x)), rowsize);
    }
    //Is this necessary?
    newimg[imgsize+1] = '\0';
Title: upside-down textures in OpenGL
Post by: Laurent on May 28, 2009, 07:57:36 am
Quote
Code: [Select]
   //Is this necessary?
    newimg[imgsize+1] = '\0';

No, it's not a string :D

And you should really use std::vector instead of malloc (unless your code is pure C).
Title: upside-down textures in OpenGL
Post by: vpoqol5 on May 30, 2009, 02:05:54 pm
Yes, this should be fixed in sfml
I came across it few weeks ago when I was porting part of my framework for another project to sfml, but, because I have my own implementations for every operation I need, I fixed it as easy as changing variable v to -v, better explained

Code: [Select]

glTexCoord2f(pVertex->u,pVertex->v);

(obviously, I use triangles in my rendering code)

I found a number of "misunderstandings" but they hardly make me any problem, because I don't depend on sfml functions, but I'll post all of them when I find time for it,
anyway, it's a really good library, and I'm impressed, I hardly ever used another library than my knowledge for writing portable applications and "universal" functions but I could use half of them from sfml to change mine  

great work, keep up ;)
Title: upside-down textures in OpenGL
Post by: Laurent on May 31, 2009, 05:54:37 pm
Well, I made more tests, very simple ones just displaying an OpenGL texture on a quad. They clearly demonstrate that the texture origin is at the top-left corner of the image. More researches on Google resulted in 50% messages saying it's top-left, and the 50 other % saying it's bottom-left.

What a confusion :lol:

Anyway, based on my tests I'm not going to change SFML's behaviour, unless someone clearly proves me I'm wrong.
Title: upside-down textures in OpenGL
Post by: dabo on May 31, 2009, 06:53:15 pm
I'm pretty sure it says in my OpenGL book it's bottom-left. I wish I had it with me so that I could check for sure.
Title: upside-down textures in OpenGL
Post by: vpoqol5 on May 31, 2009, 08:35:46 pm
Ok, I'll put it this way
I'm programming in opengl for about five years now and this is my "job", so I'm pretty sure that origin is at bottom left,
you can see it in superbible 1,2,3 and 4th editiion, in beginning opengl game programming on page 151, the offical guide to learning opengl version 2.1 6th edition on page 378, OpenGL Graphics
Through Applications page 171, 175

But actually don't mind that, my question is, where have you seen it as being applied to top left? This is first time that I hear about that, truly :)

The mapping process involves moving from the texture space to the Cartesian space, and origin is defined as bottom left in both scenarios
Title: upside-down textures in OpenGL
Post by: Tabasco on May 31, 2009, 11:34:37 pm
It's been bottom left since I've been using opengl and every other engine or framework I've used treats it that way.  When I export models from blender, and presumably any other modeling software, the UV's are/would be all upside down.
The article I posted is from opengl.org and the author (http://en.wikipedia.org/wiki/Mark_Kilgard) is credible, so if that's not enough proof, I don't know what is.
It really is shocking to me that it isn't documented any better than it is but opengl clearly reads textures starting with the bottom row.
Title: upside-down textures in OpenGL
Post by: Laurent on June 01, 2009, 05:36:12 pm
Ok, so I'm obviously wrong (which I expected) :)

The thing is that (0, 0) maps to the first pixel of the array you pass to glTexImage2D ; if it's the top-left corner of the image then (0, 0) will map to the top-left corner, same for the bottom-left corner. So this is not a matter of what pixel (0, 0) maps to, it's more a matter of convention to follow.

The conclusion is that I could easily change my convention for SFML, everything would still work. But then not only OpenGL will be affected, it's the whole interface of sf::Image that will follow the new convention ; do users expect the pixel at (0, 0) to be the bottom-left one? Isn't it too dangerous to adopt the OpenGL's convention?
Title: upside-down textures in OpenGL
Post by: Tabasco on June 01, 2009, 05:42:45 pm
I'm content to just flip the sf::Image myself.  I would say that if anything needs done in SFML it would be to provide a convenience function like Image->Flip or simply provide a comment in the OpenGL example describing the issue. (Maybe both?)
Title: upside-down textures in OpenGL
Post by: vpoqol5 on June 03, 2009, 11:33:53 am
The most effective thing would be to create separate inherited sf::Image class like, sf::GLimage with changed function(s), but since that really isn't needed, you could rather provide argument option in existing function like GL_TEXTURE to put in Load...Image or wherever, default to be none, or new function like CreateGLTexture which won't be private, I would go for an argument, since you won't have to recreate texture
anyway, this should be simple and understandable, so now we wait ;)
Title: upside-down textures in OpenGL
Post by: Laurent on June 03, 2009, 11:57:14 am
Well, if I ever implement something to work around that, it would rather be a Image::Flip() function ;)

But I wonder if bottom-left corner is really always the standard. For example, I guess it is not the case for multi-API engines using both DirectX and OpenGL, as DirectX is using top-left.
Title: upside-down textures in OpenGL
Post by: Tabasco on June 03, 2009, 03:06:58 pm
Nobody has suggested that it's always the standard, only that it's the standard in OpenGL.
My guess would be that multi-API engines simply store the texture based on the standard for what API they're using.  In addition to DirectX using top-left origin for UV's, the texture is probably not stored upside-down, so the UV's and textures you would get from modeling software would work either way.
Title: upside-down textures in OpenGL
Post by: Meltra Bour on August 10, 2009, 10:25:41 am
I just ran in to this texture problem as well ... Images are not the only problem, fonts seem to have the same problem ... loading ttf files puts them upside down it seems the whole of sfml follows left-top as standard ... witch is fun ... I like to confuse people so  :P

Good thing that I don't need collision detection on text ...
Code: [Select]

glRotatef(180.0, 1.0, 0.0, 0.0);    // Silly sfml font ... flip it up side down


any way a bump, giving people a option to flip textures and fonts around would be appreciated. one vote for sf::Image::flip() and sf::Font::flip()

and euh I have no clue about standards but the way I learned it for opengl has always been bottom-left.
Title: upside-down textures in OpenGL
Post by: Laurent on August 10, 2009, 10:38:36 am
This issue is really annoying. Trust me, I'd love to follow the OpenGL rules, that would make some parts of my internal code cleaner. But OpenGL is the one that doesn't follow the "standards". It rather follows the "natural" direction of Y axis, which is unfortunately not the same used in computer graphics in general (at least in our context).

Everything else involved in SFML has its 0 natively mapped to the top: window position, pixels in images files, ... If I change the Y axis direction then I'll get more people confused because it no longer matches these other conventions.

But like I already said, OpenGL doesn't enforce a direction on the Y axis. I've always worked with 0 on top in OpenGL and I never got any problem. This is mostly in your mind ;)
Just use SFML's convention rather than trying to make me change it.
Title: upside-down textures in OpenGL
Post by: _seb_ on August 10, 2009, 11:19:00 am
For information:
OpenGL origin is at the lower left but texture origin is at upper left.
See http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall/
Item 12 OpenGL's Lower Left Origin
Title: upside-down textures in OpenGL
Post by: l0calh05t on August 10, 2009, 01:15:08 pm
Quote from: "Laurent"
This issue is really annoying. Trust me, I'd love to follow the OpenGL rules, that would make some parts of my internal code cleaner. But OpenGL is the one that doesn't follow the "standards". It rather follows the "natural" direction of Y axis, which is unfortunately not the same used in computer graphics in general (at least in our context).


OpenGL doesn't follow the standards?!? It uses proper mathematical convention, which is 0,0 -> bottom left (and right handed coordinate system for 3D).

Quote
Everything else involved in SFML has its 0 natively mapped to the top: window position, pixels in images files, ... If I change the Y axis direction then I'll get more people confused because it no longer matches these other conventions.

But like I already said, OpenGL doesn't enforce a direction on the Y axis. I've always worked with 0 on top in OpenGL and I never got any problem. This is mostly in your mind ;)
Just use SFML's convention rather than trying to make me change it.


OpenGL convention is having the texture origin in the bottom left, so the way it is now, is extremely impractical/confusing for all the GL users.

One temporary solution would be to push a -1 scale in y direction onto the OGL texture matrix stack... (of course only for fixed function, not shaders & OGL3)
Title: upside-down textures in OpenGL
Post by: Laurent on August 10, 2009, 01:41:51 pm
Quote
OpenGL doesn't follow the standards?!? It uses proper mathematical convention, which is 0,0 -> bottom left (and right handed coordinate system for 3D).

I just said it doesn't follow the 2D computer graphics standards. Proper mathematical convention is fine, but I think it's inappropriate in this context, where everything else uses a top-left origin.

As SFML is dealing with more stuff related to 2D computer graphics (GUI, images, ...) than OpenGL, it can't be based on the same convention. I had to choose the more widely used.

Quote
OpenGL convention is having the texture origin in the bottom left, so the way it is now, is extremely impractical/confusing for all the GL users.

I know... I just want you to think more globally, not just with OpenGL in mind. Would you like window.SetPosition(0, 0) to put your window at the bottom-left corner of your desktop? Or image.GetPixel(0, 0) to be the bottom-left pixel of your image?

Quote
One temporary solution would be to push a -1 scale in y direction onto the OGL texture matrix stack...

I think that it would mess up many other things.
Title: upside-down textures in OpenGL
Post by: l0calh05t on August 10, 2009, 03:49:05 pm
Quote from: "Laurent"

I just said it doesn't follow the 2D computer graphics standards. Proper mathematical convention is fine, but I think it's inappropriate in this context, where everything else uses a top-left origin.

If you are using 2D graphics, you are probably using SFML-Graphics, but if you are using 3D graphics, and therefore directly using textures this is inappropriate. Furthermore this change would be hidden to users of SFML-Graphics... (Or are images ever used directly without sprites?)

Quote
As SFML is dealing with more stuff related to 2D computer graphics (GUI, images, ...) than OpenGL, it can't be based on the same convention. I had to choose the more widely used.

I know... I just want you to think more globally, not just with OpenGL in mind. Would you like window.SetPosition(0, 0) to put your window at the bottom-left corner of your desktop? Or image.GetPixel(0, 0) to be the bottom-left pixel of your image?


Actually, yes, I would like that!  :wink:

Quote
I think that it would mess up many other things.

Depends on where it is done. But it isn't a proper solution anyways... just a quick, hacky fix for fixed-function GL
Title: upside-down textures in OpenGL
Post by: Laurent on August 10, 2009, 03:56:05 pm
Quote
If you are using 2D graphics, you are probably using SFML-Graphics, but if you are using 3D graphics, and therefore directly using textures this is inappropriate.

If you're using 3D and textures then you're not using SFML. Except for loading images, but every image loading library loads the pixels with the origin at the top-left corner anyway.
Title: upside-down textures in OpenGL
Post by: l0calh05t on August 10, 2009, 04:41:18 pm
Quote from: "Laurent"
If you're using 3D and textures then you're not using SFML. Except for loading images, but every image loading library loads the pixels with the origin at the top-left corner anyway.


So... if I'm using SFML-Window, SFML-Audio and SFML-Network, but not SFML-Graphics, I'm not using SFML?

(Font [not String] and Image are the only parts of SFML-Graphics I'm still using, but they'll probably be removed at some point...)

EDIT:
About no libs which load with a pixel origin at the bottom left.... try SOIL with SOIL_FLAG_INVERT_Y. And DevIL also supports it via ilOriginFunc
Title: upside-down textures in OpenGL
Post by: Laurent on August 10, 2009, 05:06:55 pm
Quote
So... if I'm using SFML-Window, SFML-Audio and SFML-Network, but not SFML-Graphics, I'm not using SFML?

I just meant "you're not using SFML for 3D and textures" -- because that's what you were talking about :)

Quote
About no libs which load with a pixel origin at the bottom left.... try SOIL with SOIL_FLAG_INVERT_Y. And DevIL also supports it via ilOriginFunc

Ok, most of the OpenGL-oriented image libraries provide an option for flipping the image. I admit that SFML could do it as well -- but here we're just talking about a helper function, not a new default behaviour.

Anyway, if you want quick results you shouldn't wait for me, you'd better implement your own FlipPixels function ;)
Title: upside-down textures in OpenGL
Post by: l0calh05t on August 10, 2009, 06:16:03 pm
Quote from: "Laurent"
Anyway, if you want quick results you shouldn't wait for me, you'd better implement your own FlipPixels function ;)


I never really considered it a problem... using SOIL directly gives me a lot more options anyways... It was a bit confusing though as I wrote my own text renderer (based on sf::Font using VBOs)