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

Should I vertically flip the lines of an image loaded with stb_image to use in OpenGL?

本文关键字:OpenGL 图像 加载 垂直翻转 stb 我应该 image      更新时间:2023-10-16

我正在开发一个OpenGL驱动的2d引擎。

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

你可能猜到了,我的纹理是垂直翻转的,但我100%确信我的UV是正确指定的。

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

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

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

1-如果这是由像素数据的stbi_load存储引起的,我可以在加载时将其反转。出于性能原因,我有点担心,因为我使用纹理阵列(glTexture3d(制作精灵动画,这意味着我需要单独反转纹理平铺,这似乎很痛苦,不是一个通用的解决方案。

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

第三种可能的选择是使用glPixelStore来指定输入数据。。。但我找不到一种方法来告诉它,传入的像素是垂直翻转的。

你对处理我的问题有什么建议?我想我不可能是唯一一个使用stbi_load+OpenGL并有这个问题的人。

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

编辑:我回答了我自己的问题。。。请参见下文

我知道这个问题很老了,但这是谷歌上解决这个问题的第一个结果,所以我想我应该提供一个更新的解决方案。

在最初提出这个问题后的某个时间,stb_image.h添加了一个名为";stbi_set_flip_verticaly_;,简单地将true传递给该函数将使其按照OpenGL期望的方式输出图像,从而消除手动翻转/纹理坐标翻转的需要。

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

同样值得注意的是,在stb_image的当前实现中,他们逐像素翻转图像,这并不完全是性能上的。这可能会在以后发生变化,因为他们已经将其标记为优化 编辑:看起来他们已经换成了memcpy,这应该会快一点。

好的,我会回答我自己的问题。。。我浏览了两个库(stb_image和OpenGL(的文档。

以下是适当的参考位:

glTexImage2D对数据指针参数说明如下:">第一个元素对应于纹理图像的左下角。随后的元素从左到右依次经过纹理图像最低行中的其余纹素,然后依次进入纹理图像的较高行。最后一个元素对应纹理图像的右上角。"从http://www.opengl.org/sdk/docs/man/xhtml/glTexImage2D.xml

stb_image库对加载的图像像素是这样说的:"图像加载器的返回值是一个指向像素数据的‘无符号字符*’。像素数据由*x个像素的*y条扫描线组成,每个像素由N个交错的8位分量组成;指向的第一个像素位于图像的左上角。"http://nothings.org/stb_image.c‎

因此,该问题与图像加载库和OpenGL之间的像素存储差异有关。如果我加载了PNG以外的其他文件格式也没关系,因为stb_image为它加载的所有格式返回相同的数据指针。

所以我决定在OglTextureFactory中交换stb_image返回的像素数据。通过这种方式,我保持了我的方法平台的独立性。如果加载时间以后成为一个问题,我将删除加载时的翻转,转而在GPU上做一些事情。

希望这对将来的其他人有所帮助。

是的,你应该这样做。只需在加载图像之前调用STBI函数即可轻松完成:

stbi_set_flip_vertically_on_load(true);  

由于这是一般图像库和OpenGL之间相反的假设,我认为最好的方法是操纵垂直UV坐标。这只需要最少的工作量,并且在使用任何图像库加载图像并将其传递给OpenGL时始终是相关的。

在顶点填充中使用1.0f-uv.y馈送tex坐标,或者在着色器中反转。

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