从帧缓冲区对象读取时,OpenGL 纹理坐标是相反的
Posted
技术标签:
【中文标题】从帧缓冲区对象读取时,OpenGL 纹理坐标是相反的【英文标题】:OpenGL texture coordinates are opposite when reading from a framebuffer object 【发布时间】:2018-01-06 03:31:14 【问题描述】:如果我将文件图像中的纹理加载到 OpenGL 中并创建一个垂直放置的平面,如果我将左上角的顶点设置为纹理坐标 (0, 0),则该点的纹理将在左上角采样您在应用程序中打开的图像。
但是,当我渲染到帧缓冲区并将其颜色附件绑定为纹理时,坐标为 (0, 0) 的左上角顶点将从左下角采样,如果此帧缓冲区显示到屏幕。换句话说,当从帧缓冲纹理中采样时,Y 似乎是反转的。
无论我将 glClipControl 设置为 GL_UPPER_LEFT 还是 GL_LOWER_LEFT,此纹理采样行为都是相同的,即,它将采样帧缓冲区纹理的左下角视为 (0, 0)。我注意到这一点是因为我将我的 GUI 渲染到帧缓冲区,然后渲染到默认帧缓冲区,而从图像左上角的文件样本 (0, 0) 加载的正常图像纹理,从帧缓冲纹理:
这是正常的吗,我可以让它从帧缓冲区纹理中采样 (0, 0) 是左上角吗? glClipControl(GL_UPPER_LEFT) 对这个特定的东西没有任何影响?我很困惑。
【问题讨论】:
【参考方案1】:我认为换个角度看可能会解决问题。
纹理坐标 (0, 0) 不是指纹理的左上角或左下角像素,而是指纹理的第一个像素。同样,(1, 1) 不是指右下角或右上角的像素,而是指最后一个像素。
在 OpenGL 中,纹理的第一个像素被认为是左下角的像素。
但是,在大多数图像格式中,按照惯例,文件中的第一个像素被认为是左上角的像素。
换句话说,从 OpenGL 的角度来看,当图像加载到纹理中时,纹理实际上是上下颠倒的。
这解释了为什么从渲染目标和从图像文件加载的图像进行采样之间存在差异。
现在glClipControl(GL_UPPER_LEFT, ...)
呢?
调用glClipControl(GL_UPPER_LEFT, ...)
对纹理采样没有影响。它不影响图像的采样方式,第一个像素仍然是第一个像素。
它的作用是将帧缓冲区倒置。所以当渲染目标在 (0, 0) 采样时,它仍然采样第一个像素,但现在它与调用 glClipControl(GL_UPPER_LEFT, ...)
之前的状态相反。
【讨论】:
这是有道理的。所以你是说让我们有一个左上角像素为 0, 0 的位图,然后用 glTexImage2D 加载它,它将读取图像缓冲区,使位图上的 0, 1 是第一个字节?这有点不方便,因为我必须将位图图像纹理视为与渲染缓冲区不同,例如,如果我有一个顶部顶点为 0、0 和 1、0 的立方体,那么我必须让我反转所有顶点,使顶部为 0、1 和 1,1。那好吧。谢谢。 我有三种可能,(1) 在对图像与渲染目标进行采样时,仅翻转纹理坐标(uv.x, 1-uv.y)
,(2) 使用glClipControl(GL_UPPER_LEFT,...)
,这样纹理和渲染目标都是首先存储左上角,(3)在将图像导入项目时翻转图像,以及(4)在加载图像时翻转图像 - 作为对图像进行的任何处理的一部分。我个人使用(4),因为我需要在使用之前对图像进行几次转换。
关于 GL_UPPER_LEFT 的有趣之处在于,我认为它被添加为更类似于 Vulkan 和 Direct3D 等其他 API,它可以翻转整个场景。为了否定这一点,我可以将投影矩阵中的 Y 值之一乘以 -1,一切都可以解决。事情是通过做这个三角形,一旦绕组 CW 现在绕组 CCW。这也没有问题,因为您可以通过 GL 调用来控制它。我还认为将它再次渲染到另一个渲染缓冲区,然后再次渲染到我的目的地一个(两次)使 Y 相反。我喜欢你的解决方案,你是什么意思我的选择(4)?当你
渲染到一个你在加载时不能翻转的缓冲区,因为你没有加载它,或者你在谈论使用选项(3)和(4)加载图像文件?我喜欢简单地使用单独的着色器来对 Y 进行倒置采样的想法。以上是关于从帧缓冲区对象读取时,OpenGL 纹理坐标是相反的的主要内容,如果未能解决你的问题,请参考以下文章
关于 OpenGL 纹理、帧缓冲区和 UV 坐标的问题 [关闭]