将 Opengl 纹理从第一个 fbo 绑定到第二个 fbo,使用着色器并渲染第二个结果(乒乓球)
我一直在研究乒乓球着色,并认为在上一个问题之后我已经解决了它。然而,随着进一步的着色器知识,看起来虽然我能够在 FBO A 和 FBO B 上运行着色器,但 A 的输出不会用作 B 的源。换句话说,我没有正确绑定它。
我正在使用的代码如下。第二个着色器的输出显示基于颜色的输出,但第一个着色器将数据设置为灰度。所以我知道这没有按要求工作。
如果有任何(进一步!!)帮助,我将不胜感激。
下面的代码,
干杯,
西蒙
- (void) PingPong:(CVImageBufferRef)cameraframe;
{
// Standard texture coords for the rendering pipeline
static const GLfloat squareVertices[] = {
-1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, 1.0f,
};
static const GLfloat textureVertices[] = {
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
0.0f, 0.0f,
};
if (context)
{
[EAGLContext setCurrentContext:context];
}
// Create two textures with the same configuration
int bufferHeight = CVPixelBufferGetHeight(cameraframe);
int bufferWidth = CVPixelBufferGetWidth(cameraframe);
// texture 1
glGenTextures(1, &tex_A);
glBindTexture(GL_TEXTURE_2D, tex_A);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Using BGRA extension to pull in video frame data directly
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bufferWidth, bufferHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, CVPixelBufferGetBaseAddress(cameraframe));
// Texture 2
glGenTextures(1, &tex_B);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Bind framebuffer A
glBindFramebuffer(GL_FRAMEBUFFER, fbo_A);
glViewport(0, 0, backingWidth, backingHeight);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex_A);
// Update uniform values
glUniform1i(uniforms[UNIFORM_VIDEOFRAME], 0);
// Update attribute values.
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
glEnableVertexAttribArray(ATTRIB_VERTEX);
glVertexAttribPointer(ATTRIB_TEXTUREPOSITON, 2, GL_FLOAT, 0, 0, textureVertices);
glEnableVertexAttribArray(ATTRIB_TEXTUREPOSITON);
// Use the first shader
glUseProgram(greyscaleProgram);
// Render a quad
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// Use the second shader
glUseProgram(program);
// Bind framebuffer B
glBindFramebuffer(GL_FRAMEBUFFER, fbo_B);
// Bind texture A and setup texture units for the shader
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex_A);
// Render output of FBO b is texture B
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex_B, 0);
// Update uniform values
glUniform1i(uniforms[UNIFORM_VIDEOFRAME], 0);
// Update attribute values.
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
glEnableVertexAttribArray(ATTRIB_VERTEX);
glVertexAttribPointer(ATTRIB_TEXTUREPOSITON, 2, GL_FLOAT, 0, 0, textureVertices);
glEnableVertexAttribArray(ATTRIB_TEXTUREPOSITON);
// Render a quad
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// Render the whole thing
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER];
glDeleteTextures(1, &tex_A);
glDeleteTextures(1, &tex_B);
}
I've been working on ping pong shading and had thought that I had cracked it after my previous question. However, with further shader knowledge it looks like while I'm able to run the shader on FBO A and on FBO B, the output from A is not used as the source to B. In other words I'm not binding it correctly.
The code I'm using is below. The output of the second shader is showing colour based output but the first shader sets the data to grayscale. So consquently I know this isn't working as required.
I'd be grateful for any (yet further!!) assistance.
Code below,
Cheers,
Simon
- (void) PingPong:(CVImageBufferRef)cameraframe;
{
// Standard texture coords for the rendering pipeline
static const GLfloat squareVertices[] = {
-1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, 1.0f,
};
static const GLfloat textureVertices[] = {
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
0.0f, 0.0f,
};
if (context)
{
[EAGLContext setCurrentContext:context];
}
// Create two textures with the same configuration
int bufferHeight = CVPixelBufferGetHeight(cameraframe);
int bufferWidth = CVPixelBufferGetWidth(cameraframe);
// texture 1
glGenTextures(1, &tex_A);
glBindTexture(GL_TEXTURE_2D, tex_A);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Using BGRA extension to pull in video frame data directly
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bufferWidth, bufferHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, CVPixelBufferGetBaseAddress(cameraframe));
// Texture 2
glGenTextures(1, &tex_B);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Bind framebuffer A
glBindFramebuffer(GL_FRAMEBUFFER, fbo_A);
glViewport(0, 0, backingWidth, backingHeight);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex_A);
// Update uniform values
glUniform1i(uniforms[UNIFORM_VIDEOFRAME], 0);
// Update attribute values.
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
glEnableVertexAttribArray(ATTRIB_VERTEX);
glVertexAttribPointer(ATTRIB_TEXTUREPOSITON, 2, GL_FLOAT, 0, 0, textureVertices);
glEnableVertexAttribArray(ATTRIB_TEXTUREPOSITON);
// Use the first shader
glUseProgram(greyscaleProgram);
// Render a quad
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// Use the second shader
glUseProgram(program);
// Bind framebuffer B
glBindFramebuffer(GL_FRAMEBUFFER, fbo_B);
// Bind texture A and setup texture units for the shader
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex_A);
// Render output of FBO b is texture B
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex_B, 0);
// Update uniform values
glUniform1i(uniforms[UNIFORM_VIDEOFRAME], 0);
// Update attribute values.
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
glEnableVertexAttribArray(ATTRIB_VERTEX);
glVertexAttribPointer(ATTRIB_TEXTUREPOSITON, 2, GL_FLOAT, 0, 0, textureVertices);
glEnableVertexAttribArray(ATTRIB_TEXTUREPOSITON);
// Render a quad
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// Render the whole thing
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER];
glDeleteTextures(1, &tex_A);
glDeleteTextures(1, &tex_B);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为可能发生的情况是您仍在渲染到帧缓冲区内存而不是纹理内存中。 iirc glFramebufferTexture2D 不充当解析/复制,而是将帧缓冲区绑定到纹理,以便将来的渲染操作写入纹理。您可能会遇到更多问题,但我很确定您对 glFramebufferTexture2D 的调用应该在第一次调用 glBindFramebuffer 之后立即发生。这可能不是您唯一的问题,但它似乎是一个重要的问题。
I think what might be happening is that you are still rendering into frame buffer memory and not texture memory. iirc glFramebufferTexture2D does not act as a resolve/copy but instead binds the framebuffer to the texture so that future render operations get written to the texture. You could have more problems however I'm pretty sure that your call to glFramebufferTexture2D should happen directly after your first call to glBindFramebuffer. This may not be your only problem, but it seems to be a significant one.