我有一个应用程序需要执行以下操作:
- 将纹理从磁盘加载到 GL 纹理中
- 在其上运行图像过滤器(通过 FBO 将其渲染到另一个纹理上)
- 在屏幕上显示生成的纹理
我有那么多工作。
接下来,我希望能够将第 2 步移至单独的共享 GL 上下文。
在初始化时,我创建了一个共享上下文:
rootContext = CGLGetCurrentContext();
CGLPixelFormatObj pf = CGLGetPixelFormat(rootContext);
CGLCreateContext(pf, rootContext, &childContext);
...然后使其成为最新并在其上设置帧缓冲区...
CGLSetCurrentContext(childContext);
glGenTextures(1, &childTexture);
glBindTexture(GL_TEXTURE_2D, childTexture);
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, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glGenFramebuffers(1, &childFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, childFramebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, childTexture, 0);
然后,当需要渲染每一帧时,我childContext
将其设为当前并渲染:
CGLSetCurrentContext(childContext);
glBindFramebuffer(GL_FRAMEBUFFER, childFramebuffer);
glUseProgram(childProgram);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, inputTexture);
glUniform1i(childTextureUniform, 0);
glBindBuffer(GL_ARRAY_BUFFER, childQuadPositionBuffer);
glVertexAttribPointer(childPositionAttribute, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*2, (void*)0);
glEnableVertexAttribArray(childPositionAttribute);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, childQuadElementBuffer);
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, (void*)0);
glDisableVertexAttribArray(childPositionAttribute);
glUseProgram(0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
...然后我制作rootContext
当前并将 FBO 的纹理渲染到屏幕:
CGLSetCurrentContext(rootContext);
glUseProgram(rootProgram);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, childTexture); // This texture was created and populated on childContext.
glUniform1i(rootTextureUniform, 0);
glBindBuffer(GL_ARRAY_BUFFER, rootQuadPositionBuffer);
glVertexAttribPointer(rootPositionAttribute, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*2, (void*)0);
glEnableVertexAttribArray(rootPositionAttribute);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, rootQuadElementBuffer);
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, (void*)0);
glDisableVertexAttribArray(rootPositionAttribute);
glUseProgram(0);
如果我注释掉CGLSetCurrentContext(childContext);
电话,这将非常有效。
但是,如果我切换到共享上下文以渲染到 FBO,我会在屏幕上看到出现故障的垃圾,好像什么都没有渲染到childTexture
:
...这真的很酷,但我会在这里寻求一种更现实主义的美学。
关于在使用共享上下文时如何使其工作的任何想法?
我已经试过了
- 创建共享上下文时检查
CGLError
s — 没有错误;它已成功创建。 - 检查
glGetError()
——没有错误。 - 检查
glCheckFramebufferStatus()
- 它是GL_FRAMEBUFFER_COMPLETE
. - 按照@datenwolf 的建议,
glBindTexture(GL_TEXTURE_2D, 0);
在每次通话后进行通话。glDisableVertexAttribArray()
不用找了。
完整的源代码
我创建了 2 个简单的测试应用程序,它们都表现出相同的问题:
- http://softpixel.com/~smokris/FBOTest-Cocoa.zip — 使用 Cocoa 设置 GL 窗口
- http://softpixel.com/~smokris/FBOTest-Qt.zip — 使用 Qt 设置 GL 窗口