OpenGL通过FBO渲染到纹理——与正常纹理相比,显示不正确



对纹理绑定的屏幕外帧缓冲区对象进行屏幕外渲染应该很简单,但我遇到了一个无法解决的问题。

我的完整示例程序(目前仅限2D!)在这里:

http://pastebin.com/hSvXzhJT

请参阅下面的一些描述。

我正在创建一个rgba纹理对象512x512,将其绑定到FBO。此时不需要深度或其他渲染缓冲区,严格来说是2D。

以下极其简单的着色器渲染到此纹理:

顶点着色器:

varying vec2 vPos; attribute vec2 aPos;
void main (void) {
    vPos = (aPos + 1) / 2;
    gl_Position = vec4(aPos, 0.0, 1.0);
}

在aPos中,它只得到一个VBO,其中包含四进制(-1,-1::1,-1:,1,1:,-1)的4个xy坐标

因此,尽管帧缓冲区的分辨率理论上应该达到512x512,但显然着色器会按照GLs-1.1 coords范式将其"纹理"渲染到"全屏(离屏)四边形"上。

片段着色器:

varying vec2 vPos;
void main (void) {
    gl_FragColor = vec4(0.25, vPos, 1);
}

因此,它设置了一个完全不透明的颜色,红色固定在0.25,绿色/蓝色取决于0和1之间的x/y。

在这一点上,我的假设是512x512纹理被渲染,仅显示-1.1全(离)屏幕四边形,片段从0..1变为绿色/蓝色。

这就是我的屏幕外设置。在屏幕上,我有另一个真正可见的全屏四边形,有4个xyz坐标{-1,-1,1:::1,-1,1:::1,1,1::-1,1,1}。同样,现在这是2D,所以没有矩阵,所以z总是1。

这个四边形是由不同的着色器绘制的,只需渲染给定的纹理、文本书GL-101样式即可。在上面链接的示例程序中,我有一个简单的布尔切换doRtt,当它为false(默认值)时,根本不执行对纹理的渲染,该着色器只是显示使用当前目录中的texture.jpg。

此doRtt=false模式显示第二个屏幕上的四元渲染器"正确"满足我当前的要求,并按照我的意愿执行纹理处理:垂直重复两次,水平重复两次(稍后将被钳制,重复仅用于测试),否则不使用纹理过滤或mipmapping进行缩放。

因此,无论窗口(以及视图端口)的大小如何调整,我们总是会看到一个全屏四边形,其中一个纹理水平重复两次,垂直重复两次。

现在,在doRtt=true的情况下,第二个着色器仍然可以完成它的工作,但纹理从未完全正确缩放或绘制,这一点我不确定,因为不幸的是,我们不能只说"嘿,gl,将这个FBO保存到磁盘以进行调试"。

RTT着色器确实执行了一些部分渲染(或者可能是完整渲染,再次不能确定屏幕外发生了什么…)特别是当您将视口的大小调整为比默认大小小得多时,您会看到纹理之间的中断重复,并且并不是我们非常简单的RTT片段着色器所期望的所有颜色都会显示出来。

(A) 或者:512x512纹理是正确创建的,但我的代码没有正确映射(但为什么使用doRtt=false,任何给定的texture.jpg文件都使用完全相同的简单纹理四元着色器,显示得很好?)

(B) 或者:512x512纹理没有正确渲染,rtt-frag着色器会根据窗口分辨率更改其输出,但为什么?对于x和y,屏幕外四边形始终为-1.1,顶点着色器始终将其映射到片段坐标0..1,对于这个简单的测试,RTT纹理始终保持在512x512!

注意,屏幕外四边形和屏幕上四边形都不会改变坐标,并且始终是"全屏"(两个维度都为-1.1)。

同样,这应该很简单。我到底错过了什么?

规格:OpenGL 4.2(但代码显然不需要任何4.2功能!),Nvidia Quadro 5010M,openSuse 12.1 64位,Golang Weekly,2012年2月22日。

首先,请尝试检查OpenGL错误。在每个OpenGL函数之后调用glGetError()。此外,您必须为绘图设置正确的视口。在绘制到FBO之前,请调用glViewport(0,0,512,512)。在绘制到屏幕之前,调用glViewport(0,0,display_width,display_height)。

此外,当您使用FBO对rttFrameTex进行渲染时,也不需要绑定它。只有在着色器中读取纹理时才需要绑定纹理。

最新更新