屏幕外渲染到纹理绑定的屏幕外帧缓冲区对象应该是如此微不足道,但我遇到了一个问题,我无法绕过头脑。
我的完整示例程序(目前只有2D!)在这里:
请参阅下面的一些说明。
我正在创建一个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 coords范例。
片段着色器:
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}。同样,现在这是2D所以没有矩阵,所以z总是1。
此四边形由不同的着色器绘制,只需渲染给定的纹理,即教科书GL-101样式。在我上面链接的示例程序中,我有一个简单的布尔切换doRtt,当这是假(默认)时,根本不执行渲染到纹理,这个着色器只显示使用当前目录中的texture.jpg。
这个doRtt = false模式显示第二个屏幕四重渲染器对于我当前的要求是“正确的”并按我的要求执行纹理:垂直重复两次,水平重复两次(稍后将被钳制,重复是仅用于测试),否则使用无纹理过滤或mipmapping进行缩放。
因此,无论窗口(以及视图端口)如何调整大小,我们总是会看到一个全屏四边形,其中单个纹理水平重复两次,垂直重复两次。
现在,在doRtt = true的情况下,第二个着色器仍然可以完成它的工作,但纹理永远不会完全正确缩放 - 或者绘制,我不确定,因为不幸的是我们不能只说“嘿gl拯救这个FBO到磁盘进行调试“。
RTT着色器执行一些部分渲染(或者可能是一个完整的渲染,再次无法确定屏幕外发生了什么......)特别是当您调整视口大小比默认大小小很多时,您会看到中断纹理重复之间,并不是我们非常简单的RTT片段着色器所预期的所有颜色确实显示出来。
(A)要么:512x512纹理是正确创建的,但我的代码没有正确映射(但是为什么doRtt = false任何给定的texture.jpg文件使用完全相同的简单纹理四边形着色器显示正常? )
(B)或:512x512纹理未正确渲染,并且rtt frag shader以某种方式根据窗口分辨率更改其输出 - 但为什么?对于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日。
答案 0 :(得分:11)
首先 - 尝试检查OpenGL错误。在每个OpenGL函数之后调用glGetError()。您还必须为绘图设置正确的视口。在绘制到FBO之前调用glViewport(0,0,512,512)。在绘制到屏幕之前调用glViewport(0,0,display_width,display_height)。
当您使用FBO渲染rttFrameTex时,也不需要绑定它。只有在着色器中读取纹理时才需要绑定纹理。