简体   繁体   English

我应该垂直翻转加载了stb_image的图像的行以在OpenGL中使用吗?

[英]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. 我正在研究一款支持OpenGL的2d引擎。

I'm using stb_image to load image data so I can create OpenGL textures. 我正在使用stb_image加载图像数据,因此我可以创建OpenGL纹理。 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 ie I'm using glm::ortho( 0, width, 0, height, -1, 1 ), not inverting 0 and height. 我知道OpenGL的UV原点是左下角,我也打算在那个空间中为我的屏幕空间2d顶点工作,即我使用的是glm :: ortho(0,width,0,height,-1,1) ),不反转0和高度。

You probably guessed it, my texturing is vertically flipped but I'm 100% sure that my UV are specified correctly. 你可能已经猜到了,我的纹理垂直翻转,但我100%确定我的UV指定正确。

So: is this caused by stbi_load's storage of pixel data? 那么:这是由stbi_load存储像素数据引起的吗? 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. 我目前只加载PNG文件,所以如果我使用其他文件格式,我不知道是否会导致此问题。 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. 我真的想把屏幕坐标保持在“标准”OpenGL空间......我知道我可以反转正交投影来修复它,但我真的不愿意。

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. 1-如果这是由像素数据的stbi_load存储引起的,我可以在加载时将其反转。 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. 出于性能原因我有点担心,因为我使用纹理数组(glTexture3d)进行精灵动画,这意味着我需要单独反转纹理贴片,这看起来很痛苦,而不是一般的解决方案。

2- I could use a texture coordinate transformation to vertically flip the UVs on the GPU (in my GLSL shaders). 2-我可以使用纹理坐标转换来垂直翻转GPU上的UV(在我的GLSL着色器中)。

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. 可能的第三个选项是使用glPixelStore来指定输入数据......但我找不到告诉它输入像素是垂直翻转的方法。

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. 我想我不能是唯一一个使用stbi_load + OpenGL并且遇到这个问题的人。

Finally, my target platforms are PC, Android and iOS :) 最后,我的目标平台是PC,Android和iOS :)

EDIT: I answered my own question... see below. 编辑:我回答了我自己的问题......见下文。

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. 在最初问这个问题之后的某个时候stb_image.h添加了一个名为“stbi_set_flip_vertically_on_load”的函数,简单地将true传递给这个函数将导致它以OpenGL期望的方式输出图像 - 从而无需手动翻转/纹理坐标翻转。

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 此外,对于那些不知道从哪里获得最新版本的人,无论出于何种原因,你都可以在github上找到它并积极参与: 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. 值得注意的是,在stb_image的当前实现中,它们逐像素地翻转图像,这并不完全符合要求。 This may change at a later date as they've already flagged it for optimsation. 这可能会在以后发生变化,因为他们已经将其标记为受害者。 However, if you're processing very large images and/or a lot of images it might be more performent to flip it yourself (and possibly contribute it hint hint ). 但是,如果您正在处理非常大的图像和/或大量图像,那么自己翻转它可能会更有效(并且可能会提示提示 )。

Ok, I will answer my own question... I went thru the documentation for both libs (stb_image and OpenGL). 好的,我将回答我自己的问题......我通过两个库(stb_image和OpenGL)的文档。

Here are the appropriate bits with reference: 以下是适当的位参考:

glTexImage2D says the following about the data pointer parameter: " The first element corresponds to the lower left corner of the texture image. Subsequent elements progress left-to-right through the remaining texels in the lowest row of the texture image, and then in successively higher rows of the texture image. The final element corresponds to the upper right corner of the texture image." glTexImage2D对数据指针参数说:“ 第一个元素对应于纹理图像的左下角。后续元素从左到右穿过纹理图像最下面的剩余纹素,然后依次进行纹理图像的较高行。最后一个元素对应于纹理图像的右上角。“ From http://www.opengl.org/sdk/docs/man/xhtml/glTexImage2D.xml 来自http://www.opengl.org/sdk/docs/man/xhtml/glTexImage2D.xml

The stb_image lib says this about the loaded image pixel: "The return value from an image loader is an 'unsigned char *' which points to the pixel data. The pixel data consists of *y scanlines of *x pixels, with each pixel consisting of N interleaved 8-bit components; the first pixel pointed to is top-left-most in the image. " From http://nothings.org/stb_image.c stb_image lib说明了加载的图像像素:“图像加载器的返回值是'unsigned char *',它指向像素数据。像素数据由* x像素的* y扫描线组成,每个像素由N个交错的8位分量; 指向的第一个像素位于图像的左上角。 “来自http://nothings.org/stb_image.c

So, the issue is related the pixel storage difference between the image loading lib and OpenGL. 因此,问题与图像加载lib和OpenGL之间的像素存储差异有关。 It wouldn't matter if I loaded other file formats than PNG because stb_image returns the same data pointer for all formats it loads. 如果我加载其他文件格式而不是PNG并不重要,因为stb_image为它加载的所有格式返回相同的数据指针。

So I decided I'll just swap in place the pixel data returned by stb_image in my OglTextureFactory. 所以我决定在我的OglTextureFactory中交换stb_image返回的像素数据。 This way, I keep my approach platform-independent. 这样,我保持我的方法独立于平台。 If load time becomes an issue down the road, I'll remove the flipping at load time and do something on the GPU instead. 如果加载时间成为问题,我会在加载时删除翻转并在GPU上执行某些操作。

Hope this helps someone else in the future. 希望这有助于将来的其他人。

Since this is a matter of opposite assumptions between image libraries in general and OpenGL, Id say the best way is to manipulate the vertical UV-coord. 由于这是一般图像库和OpenGL之间相反的假设,Id说最好的方法是操纵垂直UV-coord。 This takes minimal effort and is always relevant when loading images using any image library and passing it to OpenGL. 这需要很少的工作量,并且在使用任何图像库加载图像并将其传递给OpenGL时始终是相关的。

Either feed tex-coords with 1.0f-uv.y in vertex-population OR reverse in shader. 在着色器中使用顶点人口中的1.0f-uv.y或者着色器反转tex-coords。

 fcol = texture2D( tex, vec2(uv.x,1.-uv.y) );

Yes, you should. 是的你应该。 This can be easily accomplished by simply calling this STBI function before loading the image: 只需在加载图像之前调用此STBI函数即可轻松完成此操作:

stbi_set_flip_vertically_on_load(true);  

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM