一尘不染

OpenGL通过FBO渲染到纹理—错误的显示与正常的纹理

go

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

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

http://pastebin.com/hSvXzhJT

请参阅下面的一些说明。

我正在创建一个RGBBA纹理对象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坐标的四边形(-1,-1 :: 1,-1 :: 1,1 :: -1,1)的VBO。

因此,尽管帧缓冲分辨率理论上应为512x512,但显然着色器遵循GL -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, 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片段着色器会根据窗口分辨率更改其输出-
但是为什么呢?对于x和y,屏幕外四边形始终为-1..1,顶点着色器始终将其映射到片段坐标0..1,对于此简单测试,RTT纹理始终保持为512x512!

请注意,屏幕外的四边形和屏幕上的四边形都永远不会更改其坐标,并且始终是“全屏”(两个尺寸均为-1..1)。

同样,这应该是如此简单。我到底想念什么?

规格:OpenGL 4.2(但代码显然不需要任何4.2功能!),Nvidia Quadro 5010M,openSuse 12.1
64bit,Golang每周22-Feb-2012。


阅读 431

收藏
2020-07-02

共1个答案

一尘不染

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

同样,当您使用FBO渲染rttFrameTex时,也无需绑定它。仅当您在着色器中读取纹理时,才需要绑定纹理。

2020-07-02