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

bin*_*rez 4 c++ opengl textures

我正在研究一款支持OpenGL的2d引擎.

我正在使用stb_image加载图像数据,因此我可以创建OpenGL纹理.我知道OpenGL的UV原点是左下角,我也打算在那个空间中为我的屏幕空间2d顶点工作,即我使用的是glm :: ortho(0,width,0,height,-1,1) ),不反转0和高度.

你可能已经猜到了,我的纹理垂直翻转,但我100%确定我的UV指定正确.

那么:这是由stbi_load存储像素数据引起的吗?我目前只加载PNG文件,所以如果我使用其他文件格式,我不知道是否会导致此问题.是吗?(我现在不能测试,我不在家).

我真的想把屏幕坐标保持在"标准"OpenGL空间......我知道我可以反转正交投影来修复它,但我真的不愿意.

我可以看到两个理智的选择:

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

2-我可以使用纹理坐标转换来垂直翻转GPU上的UV(在我的GLSL着色器中).

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

您对处理我的问题有什么建议?我想我不能是唯一一个使用stbi_load + OpenGL并且遇到这个问题的人.

最后,我的目标平台是PC,Android和iOS :)

编辑:我回答了我自己的问题......见下文.

Liv*_*End 14

我知道这个问题很老了,但这是谷歌在尝试解决这个问题时的第一个结果之一,所以我想我会提供一个更新的解决方案.

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

此外,对于那些不知道从哪里获得最新版本的人,无论出于何种原因,你都可以在github上找到它并积极参与:https: //github.com/nothings/stb

值得注意的是,在stb_image的当前实现中,它们逐像素地翻转图像,这并不完全符合要求.这可能会在以后发生变化,因为他们已经将其标记为受害者.但是,如果您正在处理非常大的图像和/或大量图像,那么自己翻转它可能会更有效(并且可能会提示提示).

  • 您可以修改加载逻辑以仅遵循 stbi_set_flip_vertically_on_load 设置的顺序,从而根本不需要翻转。下一个最好的办法可能是对整行使用 memcpy 或 memmove 。 (2认同)

bin*_*rez 10

好的,我将回答我自己的问题......我通过两个库(stb_image和OpenGL)的文档.

以下是适当的位参考:

glTexImage2D对数据指针参数说:" 第一个元素对应于纹理图像的左下角.后续元素从左到右穿过纹理图像最下面的剩余纹素,然后依次进行纹理图像的较高行.最后一个元素对应于纹理图像的右上角." 来自http://www.opengl.org/sdk/docs/man/xhtml/glTexImage2D.xml

stb_image lib说明了加载的图像像素:"图像加载器的返回值是'unsigned char*',它指向像素数据.像素数据由*x像素的*y扫描线组成,每个像素由N个交织的8位分量; 第一像素指向是顶部最左侧的图像中 "从http://nothings.org/stb_image.c

因此,问题与图像加载lib和OpenGL之间的像素存储差异有关.如果我加载其他文件格式而不是PNG并不重要,因为stb_image为它加载的所有格式返回相同的数据指针.

所以我决定在我的OglTextureFactory中交换stb_image返回的像素数据.这样,我保持我的方法独立于平台.如果加载时间成为问题,我会在加载时删除翻转并在GPU上执行某些操作.

希望这有助于将来的其他人.