在 CVImageBuffer 上运行多个 OpenGL 着色器
关于我的前两个问题,我花了一周的时间试图弄清楚如何针对核心视频缓冲区运行多个着色器。我知道我需要做什么,但坦率地说,我无法让代码工作(下面粘贴的是原始的非乒乓版本)。
缺少了尤里卡时刻,我现在完全陷入困境了:)。为了简洁起见,未显示编译和链接着色器的代码。整个事情渲染(成功 - 但一个着色器覆盖了另一个 - 所以错过了重要的一步)到 GL 兼容层,并且下面有一个 UIToolbar,最终,每个着色器都有一个按钮和一个运行所有着色器的按钮。
谢谢,
西蒙
-(void) DrawFrame:(CVImageBufferRef)cameraframe;
{
int bufferHeight = CVPixelBufferGetHeight(cameraframe);
int bufferWidth = CVPixelBufferGetWidth(cameraframe);
// Create a new texture from the camera frame data, display that using the shaders
glGenTextures(1, &videoFrameTexture);
glBindTexture(GL_TEXTURE_2D, videoFrameTexture);
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));
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,
};
[self setDisplayFramebuffer];
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, videoFrameTexture);
// 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);
glUseProgram(greyscaleProgram);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
[self presentFramebuffer];
// Obviously here is where the ping pong starts (assuming correct mods
// to the framebuffer setup method below
glUseProgram(program);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
[self presentFramebuffer];
glDeleteTextures(1, &videoFrameTexture);
}
- (void)setDisplayFramebuffer;
{
if (context)
{
[EAGLContext setCurrentContext:context];
if (!viewFramebuffer)
{
[self createFramebuffers];
}
glBindFramebuffer(GL_FRAMEBUFFER, viewFramebuffer);
glViewport(0, 0, backingWidth, backingHeight);
}
}
- (BOOL)presentFramebuffer;
{
BOOL success = FALSE;
if (context)
{
[EAGLContext setCurrentContext:context];
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
success = [context presentRenderbuffer:GL_RENDERBUFFER];
}
return success;
}
- (BOOL)createFramebuffers
{
glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
// Onscreen framebuffer object
glGenFramebuffers(1, &viewFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, viewFramebuffer);
// Render buffer for final output
glGenRenderbuffers(1, &viewRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
[context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)self.layer];
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
NSLog(@"Backing width: %d, height: %d", backingWidth, backingHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, viewRenderbuffer);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
NSLog(@"Failure with framebuffer generation");
return NO;
}
return YES;
}
编辑:澄清了缺少的内容
Relating to my previous two questions I've spent a week attempting to figure out how to run multiple shaders against a core video buffer. I know what I need to do but I, frankly, can't get the code to work (pasted below is the original, non ping-pong version).
Lacking the Eureka moment I'm now totally stuck :). The code to compile and link the shaders is not shown for brevity. The whole thing renders (successfully - but one shader overwrites the other - so missing the vital step) to a GL compatible layer and theres a UIToolbar underneath which, eventually, will have a button per shader and a button to run all shaders.
Thanks,
Simon
-(void) DrawFrame:(CVImageBufferRef)cameraframe;
{
int bufferHeight = CVPixelBufferGetHeight(cameraframe);
int bufferWidth = CVPixelBufferGetWidth(cameraframe);
// Create a new texture from the camera frame data, display that using the shaders
glGenTextures(1, &videoFrameTexture);
glBindTexture(GL_TEXTURE_2D, videoFrameTexture);
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));
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,
};
[self setDisplayFramebuffer];
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, videoFrameTexture);
// 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);
glUseProgram(greyscaleProgram);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
[self presentFramebuffer];
// Obviously here is where the ping pong starts (assuming correct mods
// to the framebuffer setup method below
glUseProgram(program);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
[self presentFramebuffer];
glDeleteTextures(1, &videoFrameTexture);
}
- (void)setDisplayFramebuffer;
{
if (context)
{
[EAGLContext setCurrentContext:context];
if (!viewFramebuffer)
{
[self createFramebuffers];
}
glBindFramebuffer(GL_FRAMEBUFFER, viewFramebuffer);
glViewport(0, 0, backingWidth, backingHeight);
}
}
- (BOOL)presentFramebuffer;
{
BOOL success = FALSE;
if (context)
{
[EAGLContext setCurrentContext:context];
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
success = [context presentRenderbuffer:GL_RENDERBUFFER];
}
return success;
}
- (BOOL)createFramebuffers
{
glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
// Onscreen framebuffer object
glGenFramebuffers(1, &viewFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, viewFramebuffer);
// Render buffer for final output
glGenRenderbuffers(1, &viewRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
[context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)self.layer];
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
NSLog(@"Backing width: %d, height: %d", backingWidth, backingHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, viewRenderbuffer);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
NSLog(@"Failure with framebuffer generation");
return NO;
}
return YES;
}
Edit: Clarified what is missing
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
要进行乒乓渲染,您需要执行以下操作:
让我们调用帧缓冲区 A 和 B,以及附加的纹理 texA 和 texB:
渲染:
现在您已在 texA 中得到了着色器执行的结果。要进行乒乓球运动:
现在您已经在 texA 中得到了结果,您可以再次重复该过程,希望这会有所帮助!
To do ping-pong rendering, you need to do the following:
Let's call the Framebuffers A and B, and the attached textures texA and texB:
To render:
Now you have the result of the shader execution in texA. To do the ping-pong:
Now you have the result in texA and you can repeat the process again, hope this helps!