无法从OpenGL中的着色器访问以前渲染的纹理

时间:2011-08-23 22:55:33

标签: c opengl glsl

我有一个OpenGL程序,我正在做一些增强现实工作。它有2次通过。

首先,它使用标准OpenGL调用渲染帧。接下来,它使用着色器将相机中的帧与渲染帧进行比较。

在第一遍中,我渲染到绑定到我的帧缓冲对象的纹理,我还将相机帧上传到绑定到该对象的其他纹理。

在我的第二遍中,我的着色器可以轻松访问上传的纹理(即相机框架),但无法访问第一遍渲染的纹理

如果我制作一个调试着色器,只是将顶点颜色设置为该点纹理的颜色,那么当我使用从相机上传的纹理时,我会看到:

Successfully accessing texture

但是,如果我改变着色器而不是在第一遍中使用渲染的纹理,我会看到:

Not accessing texture successfully

我将尝试在下面提供足够的背景以明确这一点,但非常感谢任何帮助!


背景

我知道它在第一遍中正确渲染,因为我有一个调试窗口向我显示渲染结果,另外我使用Apple的OpenGL Profiler,并且可以看到所有纹理。

我基本上正在渲染像这个网站那样的纹理

http://www.songho.ca/opengl/gl_fbo.html#example

不同之处在于我从不切换帧缓冲对象。也就是说,我从不打电话给

// switch back to window-system-provided framebuffer
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

在进行初始渲染时,以及使用着色器进行比较时,是否需要使用不同的FBO?


我对可能发生的事情的另一个暗示是,如果在OpenGL分析器中我查看我的状态,它只声称GL_TEXTURE0和GL_TEXTURE4已从其默认状态更改。这些都是我明确加载像素数据的纹理。其他3个纹理在我的第一次传递中渲染。 Screenshot of OpenGL state


相关代码

// First I create the textures
glGenTextures(1, &renderTexture);
glGenTextures(1, &cameraTexture);
glGenTextures(1, &correlationTexture);

gllActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, cameraTexture);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img->width, img->height, 0,GL_BGR, GL_UNSIGNED_BYTE, img->imageData); 

glActiveTexture(GL_TEXTURE0+1);
glBindTexture(GL_TEXTURE_2D, renderTexture);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width, size.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTexture, 0);

glActiveTexture(GL_TEXTURE0+2);
glBindTexture(GL_TEXTURE_2D, correlationTexture);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width, size.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, correlationTexture, 0);

// Now I render to the renderTexture. This works fine, I can verify
// it using glReadPixels.

// However, later on when I'm ready to do the shader, I do this
// First I switch the bound texture
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,      GL_TEXTURE_2D,correlationTexture, 0); // (this has been set up earlier)
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(theProgram);
glUniform1i(renderTexLoc, 1); // This should tell it to look at the rendered texture from earlier, it does not.

2 个答案:

答案 0 :(得分:2)

啊,看起来我解决了它。在使用着色器渲染之前,我必须绑定第一遍渲染纹理:

  glActiveTexture(GL_TEXTURE0+1);
  glBindTexture(GL_TEXTURE_2D,renderTexture);

我想我对于绑定纹理与活动纹理之间究竟有什么区别仍然有点模糊,但是现在这种方法很有效。

答案 1 :(得分:0)

您不能同时读取和写入同一图像。这样做会导致未定义的行为。

您可以使用相同的纹理(不同的mipmap或阵列/立方体/ 3D纹理的图层)写入不同的图像。但是你不能在纹理中写入和读取相同的图像。

我猜你在尝试渲染第二遍之前调用了glClear(GL_COLOR_BUFFER_BIT),它覆盖了你期望从中读取的纹理。

通常,如果纹理附加到FBO,它应该绑定到上下文。反之亦然。也许你应该在两个纹理之间打乒乓球。一个是当前目的地,而另一个是前一个目的地。完成第二遍后,切换。这是一种非常常见的技术。