将屏幕外渲染到一个绑定纹理的离屏帧缓冲对象上应该很简单,但我却遇到了一个难以解决的问题。
我的完整示例程序(目前仅支持2D!)在此处:
下面是一些描述信息。
我创建了一个512x512的rgba纹理对象,并将其绑定到FBO上。这时候不需要深度或其他渲染缓冲区,严格为2D。
以下是极其简单的着色器来渲染这个纹理:
顶点着色器:
varying vec2 vPos; attribute vec2 aPos;
void main (void) {
vPos = (aPos + 1) / 2;
gl_Position = vec4(aPos, 0.0, 1.0);
}
在aPos中,这只需要获取一个包含四个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}。同样,现在是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着色器根据窗口分辨率改变其输出-但为什么?离屏四边形始终在-1..1的x和y上,顶点着色器始终将其映射到片段坐标0..1,RTT纹理对于这个简单测试始终保持在512x512!
请注意,离屏四边形和屏幕四边形都不会更改它们的坐标,并且始终是“全屏”(在两个维度上都为-1..1)。
再次强调,这应该是非常简单的。我到底错过了什么?
规格: OpenGL 4.2(但代码显然不需要任何4.2功能!),Nvidia Quadro 5010M,openSuse 12.1 64位,Golang周刊22-Feb-2012。