离屏渲染到纹理绑定的离屏帧缓冲区对象应该是微不足道的,但我遇到了一个问题,我无法理解。
我的完整示例程序(目前仅限 2D!)在这里:
http://pastebin.com/hSvXzhJT 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,绿色/蓝色取决于 0 到 1 之间的任何位置的 x/y。
此时,我的假设是渲染 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 模式表明第二个屏幕四渲染器对于我当前的要求是“正确的”,并按照我想要的方式执行纹理:垂直重复两次和水平两次(稍后将被夹紧,重复仅用于测试)此处),否则不进行纹理过滤或 mipmap 缩放。
因此,无论窗口(以及视口)的大小如何调整,我们总是会看到一个全屏四边形,其中单个纹理在水平方向上重复两次,垂直方向上重复两次。
现在,在 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 22-Feb-2012。