在 CVImageBuffer 上运行多个 OpenGL 着色器

发布于 2024-10-27 08:25:08 字数 3985 浏览 2 评论 0原文

关于我的前两个问题,我花了一周的时间试图弄清楚如何针对核心视频缓冲区运行多个着色器。我知道我需要做什么,但坦率地说,我无法让代码工作(下面粘贴的是原始的非乒乓版本)。

缺少了尤里卡时刻,我现在完全陷入困境了:)。为了简洁起见,未显示编译和链接着色器的代码。整个事情渲染(成功 - 但一个着色器覆盖了另一个 - 所以错过了重要的一步)到 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

疧_╮線 2024-11-03 08:25:08

要进行乒乓渲染,您需要执行以下操作:

  • 创建 2 个具有完全相同配置的纹理
  • 创建 2 个具有相同配置的帧缓冲区,并将一个纹理附加到每个帧缓冲区。

让我们调用帧缓冲区 A 和 B,以及附加的纹理 texA 和 texB:

渲染:

  • 将第一个着色器与 glUseProgram 一起使用。
  • 绑定帧缓冲区 A。
  • 渲染四边形。

现在您已在 texA 中得到了着色器执行的结果。要进行乒乓球运动:

  • 将第二个着色器与 glUseProgram 一起使用。
  • 绑定 Framebuffer B。
  • 绑定 texA 并为着色器设置纹理单元。
  • 渲染一个四边形。
  • 通过 glUseProgram 使用着色器。
  • 绑定Framebuffer A。
  • 绑定texB并设置纹理单元。
  • 渲染一个四边形。

现在您已经在 texA 中得到了结果,您可以再次重复该过程,希望这会有所帮助!

To do ping-pong rendering, you need to do the following:

  • Create 2 textures, with the exact same configuration
  • Create 2 Framebuffers with the same configuration, and attach one texture to each framebuffer.

Let's call the Framebuffers A and B, and the attached textures texA and texB:

To render:

  • Use the first shader with glUseProgram.
  • Bind Framebuffer A.
  • Render a quad.

Now you have the result of the shader execution in texA. To do the ping-pong:

  • Use the second shader with glUseProgram.
  • Bind Framebuffer B.
  • Bind texA and setup texture units for your shader.
  • Render a quad.
  • Use shader with glUseProgram.
  • Bind Framebuffer A.
  • Bind texB and setup texture units.
  • Render a quad.

Now you have the result in texA and you can repeat the process again, hope this helps!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文