10

我正在开发一个基于 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 :)

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

4

4 回答 4

24

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

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

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

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

于 2015-09-24T08:48:27.000 回答
13

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

以下是参考的适当位:

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

stb_image 库对加载的图像像素进行了说明:“图像加载器的返回值是指向像素数据的 'unsigned char *'。像素数据由 *x 像素的 *y 扫描线组成,每个像素由由 N 个交错的 8 位分量组成;指向的第一个像素位于图像的最左上角。 ”来自http://nothings.org/stb_image.c ‎</p>

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

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

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

于 2013-11-05T14:53:39.787 回答
2

是的你应该。这可以通过在加载图像之前简单地调用这个 STBI 函数来轻松完成:

stbi_set_flip_vertically_on_load(true);  
于 2019-05-08T17:21:48.740 回答
0

由于这是一般图像库和 OpenGL 之间的相反假设问题,我说最好的方法是操纵垂直 UV 坐标。这需要最少的努力,并且在使用任何图像库加载图像并将其传递给 OpenGL 时总是相关的。

要么在顶点填充中使用1.0f-uv.y输入tex-coords,要么在着色器中反转。

 fcol = texture2D( tex, vec2(uv.x,1.-uv.y) );
于 2019-02-23T22:48:20.900 回答