openGL invert textures orientation during pixel-transfer?
Asked Answered
T

2

15

as we all know, openGL uses a pixel-data orientation that has 0/0 at left/bottom, whereas the rest of the world (including virtually all image formats) uses left/top. this has been a source of endless worries (at least for me) for years, and i still have not been able to come up with a good solution.

in my application i want to support following image data as textures:

  1. image data from various image sources (including still-images, video-files and live-video)
  2. image data acquired via copying the framebuffer to main memory (glReadPixels)
  3. image data acquired via grabbing the framebuffer to texture (glCopyTexImage)

(case #1 delivers images with top-down orientation (in about 98% of the cases; for the sake of simplicity let's assume that all "external images" have top-down orientation); #2 and #3 have bottom-up orientation)

i want to be able to apply all of these textures onto various arbitrarily complex objects (e.g. 3D-models read from disk, that have texture coordinate information stored).

thus i want a single representation of the texture_coords of an object. when rendering the object, i do not want to be bothered with the orientation of the image source. (until now, i have always carried a topdown-flag alongside the texture id, that get's used when the texture coordinates are actually set. i want to get rid of this clumsy hack!

basically i see three ways to solve the problem.

  1. make sure all image data is in the "correct" (in openGL terms this is upside down) orientation, converting all the "incorrect" data, before passing it to openGL
  2. provide different texture-coordinates depending on the image-orientation (0..1 for bottom-up images, 1..0 for top-down images)
  3. flip the images on the gfx-card

in the olde times i've been doing #1, but it turned out to be too slow. we want to avoid the copy of the pixel-buffer at all cost.

so i've switched to #2 a couple of years ago, but it is way to complicated to maintain. i don't really understand why i should carry metadata of the original image around, once i transfered the image to the gfx-card and have a nice little abstract "texture"-object. i'm in the process of finally converting my code to VBOs, and would like to avoit having to update my texcoord arrays, just because i'm using an image of the same size but with different orientation!

which leaves #3, which i never managed to work for me (but i believe it must be quite simple). intuitively i though about using something like glPixelZoom(). this works great with glDrawPixels() (but who is using that in real life?), and afaik it should work with glReadPixels(). the latter is great as it allows me to at least force a reasonably fast homogenous pixel orientation (top-down) for all images in main memory.

however, it seems thatglPixelZoom() has no effect on data transfered via glTexImage2D, let alone glCopyTex2D(), so the textures generated from main-memory pixels will all be upside down (which i could live with, as this only means that i have to convert all incoming texcoords to top-down when loading them). now the remaining problem is, that i haven't found a way yet to copy a framebuffer to a texture (using glCopyTex(Sub)Image) that can be used with those top-down texcoords (that is: how to flip the image when using glCopyTexImage())

is there a solution for this simple problem? something that is fast, easy to maintain and runs on openGL-1.1 through 4.x?

ah, and ideally it would work with both power-of-two and non-power-of-two (or rectangle) textures. (as far as this is possible...)

Thar answered 1/6, 2013 at 17:47 Comment(7)
"rotate the images on the gfx-card" This would be a flip, not a rotation.Simonides
"normalized (2^n)" That's not what "normalized" means.Simonides
@NicolBolas: thanks, i replaced "rotate" by "flip"; i don't consider the "normalized (2^n)" terribly wrong (probably not accurate, but i guess you know what i mean), but if you come up with a better wording that helps solving my problem, i'd love to hear it.Junto
The correct phrases are "power-of-two" and "non-power-of-two". "Rectangle texture" means something very different from NPOTs.Simonides
Just FYI, but many image formats can have the origin in the bottom left. Among the most popular of those are DIB/BMP (yes! if the image height header field is negative this indicated origin in the bottom), PNG and TIFF. So the sole assumption that image file data had its origin in the top left is a wrong assumption.Miniaturist
@NicolBolas: thanks for the clarification on 2^n texturesJunto
@Miniaturist if it was only still images, i wouldn't care about the order so much and just convert the data to be bottom-up in main memory. the problem really comes in when it comes to moving images (video, live or pre-recorded). obviously there are always some formats that do it differently.Junto
S
13

is there a solution for this simple problem? something that is fast, easy to maintain and runs on openGL-1.1 through 4.x?

No.

There is no method to change the orientation of pixel data at pixel upload time. There is no method to change the orientation of a texture in-situ. The only method for changing the orientation of a texture (besides downloading, flipping and re-uploading) is to use an upside-down framebuffer blit from a framebuffer containing a source texture to a framebuffer containing a destination texture. And glFramebufferBlit is not available on any hardware that's so old it doesn't support GL 2.x.

So you're going to have to do what everyone else does: flip your textures before uploading them. Or better yet, flip the textures on disk, then load them without flipping them.

However, if you really, really want to not flip data, you could simply have all of your shaders take a uniform that tells them whether or not to invert the Y of their texture coordinate data. Inversion shouldn't be anything more than a multiply/add operation. This could be done in the vertex shader to minimize processing time.

Or, if you're coding in the dark ages of fixed-function, you can apply a texture matrix that inverts the Y.

Simonides answered 1/6, 2013 at 18:22 Comment(2)
i'm afraid i'm still in them "dark ages of fixed-function (slowly" adding ogl-3.x features). by "textures (on disk)" do you mean the image footage or texture coordinates ("3d model footage")? if it's the former, i'm out of luck as it's hard to flip a live-video in an offline process... :-)Junto
@umlaeute: You can simply flip the texture T coordinate, by applying a (1, -1, 1) scaling to the texture transformation matrix (glMatrixMode(GL_TEXTURE)).Miniaturist
C
2

why arent you change the way how you map the texture to the polygone ? I use this mapping coordinates { 0, 1, 1, 1, 0, 0, 1, 0 } for origin top left and this mapping coordinates { 0, 0, 1, 0, 0, 1, 1, 1 } for origin bottom left. Then you dont need to manualy switch your pictures.

more details about mapping textures to a polygone could be found here: http://iphonedevelopment.blogspot.de/2009/05/opengl-es-from-ground-up-part-6_25.html

Conwell answered 3/12, 2013 at 23:2 Comment(1)
Please avoid using just pasting links, please quote what is contained in the link for references.Colombo

© 2022 - 2024 — McMap. All rights reserved.