众所周知,openGL 使用左/下为 0/0 的像素数据方向,而世界其他地方(包括几乎所有图像格式)使用左/上。多年来,这一直是无休止的担忧(至少对我而言),我仍然无法想出一个好的解决方案。
在我的应用程序中,我想支持以下图像数据作为纹理:
- 来自各种图像源的图像数据(包括静止图像、视频文件和实时视频)
- 通过将帧缓冲区复制到主存储器获取的图像数据 (
glReadPixels
) - 通过将帧缓冲区抓取到纹理获取的图像数据 (
glCopyTexImage
)
(案例 #1 提供自上而下方向的图像(在大约 98% 的情况下;为简单起见,我们假设所有“外部图像”都具有自上而下的方向);#2 和 #3 具有自下而上的方向)
我希望能够将所有这些纹理应用于各种任意复杂的对象(例如从磁盘读取的 3D 模型,其中存储了纹理坐标信息)。
因此我想要一个对象的纹理坐标的单一表示。渲染对象时,我不想被图像源的方向所困扰。(直到现在,我总是topdown
在纹理 ID 旁边带有一个 -flag,它在实际设置纹理坐标时使用。我想摆脱这个笨拙的黑客!
基本上我看到了解决问题的三种方法。
- 确保所有图像数据都处于“正确”(在 openGL 术语中这是颠倒的)方向,转换所有“不正确”数据,然后将其传递给 openGL
- 根据图像方向提供不同的纹理坐标(自下而上图像为 0..1,自上而下图像为 1..0)
- 翻转 gfx 卡上的图像
在过去我一直在做#1,但结果太慢了。我们想不惜一切代价避免复制像素缓冲区。
所以几年前我已经切换到#2,但维护起来很复杂。我真的不明白为什么我应该携带原始图像的元数据,一旦我将图像传输到 gfx 卡并有一个漂亮的小抽象“纹理”对象。我正在最终将我的代码转换为 VBO,并且希望避免更新我的 texcoord 数组,因为我使用的是相同大小但方向不同的图像!
剩下的#3,我从来没有为我工作过(但我相信它一定很简单)。直觉上,我想使用类似glPixelZoom()
. 这适用于glDrawPixels()
(但谁在现实生活中使用它?),并且 afaik 它应该适用于glReadPixels()
. 后者很棒,因为它至少允许我为主内存中的所有图像强制一个相当快的同质像素方向(自上而下) 。
但是,似乎这glPixelZoom()
对通过 传输的数据没有影响glTexImage2D
,更不用说glCopyTex2D()
,所以从主存储器像素生成的纹理都将颠倒(我可以忍受,因为这只意味着我必须将所有传入的 texcoords 转换为加载它们时自上而下)。现在剩下的问题是,我还没有找到一种方法将帧缓冲区复制到glCopyTex(Sub)Image
可以与那些自上而下的texcoords一起使用的纹理(使用)(即:使用时如何翻转图像glCopyTexImage()
)
这个简单的问题有解决方案吗?快速、易于维护并在 openGL-1.1 到 4.x 上运行的东西?
啊,理想情况下,它适用于二次幂和非二次幂(或矩形)纹理。(尽可能……)