5
\$\begingroup\$

When loading a texture in OpenGL, how do I specify the origin of the data I am loading?

For example, how would I load a Targa that has it's origin at the top left instead of the bottom left of the image?

\$\endgroup\$

3 Answers 3

4
\$\begingroup\$

You can't, at least not directly. The origin of textures in OpenGL is the lower-left corner. You need to vertically flip your image if it doesn't match this coordinate system. So it's really an image processing problem, not an OpenGL problem.

(Alternatively, you can flip all your texture coordinates that refer to the image.)

\$\endgroup\$
4
  • \$\begingroup\$ Check my answer, there's actually a way to change the origin of texture (and apply other transforms aswell): the GL_TEXTURE matrix. \$\endgroup\$
    – kaoD
    Commented Mar 25, 2012 at 21:43
  • 1
    \$\begingroup\$ That's what I meant, essentially, by "you can flip all your texture coordinates that refer to the image." In modern OpenGL you'd do this by some transformation in the shader, not by the GL_TEXTURE matrix stack. \$\endgroup\$ Commented Mar 25, 2012 at 21:44
  • \$\begingroup\$ Well, that's changing the origin directly, isn't it? Technically any transform is just transforming the origin... But that's just technically :P I just though you meant transforming geometry. \$\endgroup\$
    – kaoD
    Commented Mar 25, 2012 at 21:52
  • \$\begingroup\$ Depends on how much you squint when you look at it. There's no real moral difference between transforming the input texture vs. transforming the UVs in the model vs. adding an affine transformation on your texture coordinate vs. adding a line or two of code in a shader. The only difference is convenience and performance. Personally, I'd rather get all my input textures into the OpenGL paradigm so I don't forget this one transformation elsewhere (especially if you ever access a texture in the shader that isn't directly tied to geometry). \$\endgroup\$ Commented Mar 25, 2012 at 21:55
6
\$\begingroup\$

As a first solution, you could just change the coordinates accordingly yourself when calling glTexCoord (or when setting the texture coordinates in your vertex array.)

To flip your texture origin you could easily flip your coordinate system. A naive solution would be glScalef(1.0f, -1.0f, 1.0f); (or alternative methods in modern matrix-less OpenGL), effectively flipping your Y coordinates and putting the origin at the top-left corner. Beware: you're not actually flipping the texture, but flipping your geometry, although it's a very easy solution if you're just drawing a simple scene like a full-screen quad.

That's rather hacky and will not work for complex situations (without hacking even more.) The correct way to go in old OpenGL is the GL_TEXTURE matrix (which doesn't seem to be very popular, even when matrices were available.) It behaves exactly like any other matrix (see this link about transforms @ Songho.)

Another approach to this problem (the correct one IMHO, fully-compatible with modern OGL) is processing the image in shaders. It's very simple: your new texCoord would be 1.0 - texCoord (for normalized textures.) This is fully compatible with matrix-less OpenGL (which you should be aiming for, btw) and will let you do all kind of further image processing.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Or you can just flip the texture data either before you load it or at load time. That way, you shaders don't have a random 1.0-texCoord taking up unnecessary time. \$\endgroup\$ Commented Mar 26, 2012 at 1:17
  • \$\begingroup\$ Note that all of those solutions have serious drawbacks in terms of API portability, for engines that want to have both D3D and GL backends. It's deeply unfortunate that there isn't a way in GL to flip the coordinates, since all the other API differences are more or less easy to work around (lack of true proper threading in GL being the other excception, but only compared to D3D11). \$\endgroup\$ Commented Mar 26, 2012 at 6:37
  • \$\begingroup\$ @seanmiddleditch: "Note that all of those solutions have serious drawbacks in terms of API portability, for engines that want to have both D3D and GL backends." That's why asset conditioning pipelines exist. Just process your textures for your GL backend through a "flip" command. It's not that hard. I even wrote one that flips S3TC compressed formats. Also, isn't it equally unfortunate that D3D doesn't have a way to flip its texture coordinates? Why call out GL for not being interoperable with D3D, when GL was here first? \$\endgroup\$ Commented Mar 26, 2012 at 8:31
  • \$\begingroup\$ @NicolBolas: While that does work, it then also means that all the textures show up flipped in any debugging tools you might use, which is a little awkward (though certainly not a show stopper). So far as why I call out GL, given that it is the more extensible API of the two by far I'm just really surprised that there isn't already a well-established GL extension for texture coordinate flipping. \$\endgroup\$ Commented Mar 26, 2012 at 9:55
1
\$\begingroup\$

You should flip the image data before uploading it to the GPU. Depending on the image library you are using it might be possible to flip the images already when loading without extra effort.

Don't try to workaround this by flipping texture coordinates or altering texture matrices. Those are not general solutions and only pollutes your code here and there. They are also incompatible with Framebuffer objects, since those expect the texture coordinates to be without any flipping.

Note that cube maps should not be flipped before uploading them. Those can be used directly as they are.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .