7

到纹理绑定的屏幕外帧缓冲区对象的屏幕外渲染应该是如此微不足道,但我遇到了一个问题,我无法绕开我的头。

我的完整示例程序(目前仅 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 中,这只是获得一个包含 4 个 xy 坐标的四边形的 VBO (-1, -1 :: 1, -1 :: 1, 1 :: -1, 1)

因此,尽管帧缓冲区分辨率理论上应该是 512x512,但显然着色器将其“纹理”渲染到“全(关闭)屏幕四边形”,遵循 GLs -1..1 坐标范式。

片段着色器:

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

所以它设置了一个完全不透明的颜色,红色固定为 0.25,绿色/蓝色取决于 x/y 介于 0 和 1 之间的任何位置。

在这一点上,我的假设是渲染 512x512 纹理仅显示 -1..1 全(关闭)屏幕四边形,从 0..1 开始对绿色/蓝色进行片段着色。

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

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

这种 doRtt=false 模式表明第二个屏幕四边形渲染器对于我当前的要求是“正确的”,并按照我的意愿执行纹理:垂直重复两次,水平重复两次(稍后将被钳制,重复只是为了测试此处),否则在没有纹理过滤或 mipmapping 的情况下进行缩放。

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

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

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

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

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

请注意,屏幕外四边形和屏幕上四边形都不会改变它们的坐标,并且始终是“全屏”(两个维度均为-1..1)。

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

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

4

1 回答 1

12

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

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

于 2012-03-09T07:56:12.340 回答