• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

ios - 如何在 UIView 和另一个线程之间共享 CVOpenGLESTextureCache?

[复制链接]
菜鸟教程小白 发表于 2022-12-12 12:54:42 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

这是节奏拳手或任何知道答案的人的问题:

根据线程:How to use OpenGL ES on a separate thread on iphone?

Rhythmic Fistman 发现“iOS5 的 CVOpenGLESTextureCaches 本质上使纹理上传免费,因此我不再需要 shareGroups,而且我的代码更简单、更快。”

我目前正在开发一个应用程序,它可以绘制 3D 图形并将其保存在电影文件中。据我了解,UIView 的 OpenGL ES 帧缓冲区必须以 colorRenderBuffer 为后盾,而不是 CVOpenGLESTextureCache,这是电影文件保存 3D 图形的 opengl 纹理的方式。

我不希望 OpenGLES 两次渲染相同的 3D 图形,我想分享渲染的结果。

您能否分享有关如何使用 CVOpenGLESTextureCache 在保存 openGL 纹理的工作线程和显示帧缓冲区的主线程 UIView 之间共享的知识和/或源代码?

提前致谢。

问候,霍华德

===========更新========

谢谢,我按照 Brad 的回答和 RosyWriter 示例代码编写了一些简单的代码,从 avCaptureOutput Dispatch 队列线程渲染最终缓冲区和主 UIView。 (稍后会润色)。

有 2 个 OpenGL-ES 2.0 上下文,1 个为 UIWebView 创建的 mainContext,2 个 workingContext,为 avCaptureOutput 的调度队列创建的。他们共享同一个组。

到目前为止一切顺利。会试试看有没有出现画面撕裂的效果。

非常感谢!

下面是我的代码:

//Draw texture
-(void)DrawCVPixelBufferRef)updatedImageBuffer
{
    CVOpenGLESTextureRef cvTexture;

    /////////////////////////////////////////////
    //first draw graphics to the CVPixelBufferRef
    /////////////////////////////////////////////
    //creates a live binding between the image buffer and the underlying texture object.
    CVReturn err = CVOpenGLESTextureCacheCreateTextureFromImage(
                                                                kCFAllocatorDefault,
                                                                cvTextureCache,
                                                                updatedImageBuffer,
                                                                NULL,
                                                                GL_TEXTURE_2D,
                                                                GL_RGBA,//  opengl format
                                                                esContext.bufWidth,
                                                                esContext.bufHeight,
                                                                GL_BGRA,// native iOS format
                                                                GL_UNSIGNED_BYTE,
                                                                0,
                                                                &cvTexture);
    if (err == kCVReturnSuccess) {
        assert(CVOpenGLESTextureGetTarget(cvTexture) == GL_TEXTURE_2D);
        GLint texId = CVOpenGLESTextureGetName(cvTexture);
        if (!workingContext || [EAGLContext setCurrentContext:workingContext] == NO) {
            NSLog(@"SwapBuffers: [EAGLContext setCurrentContext:workingContext] failed");
            return;
        }
        glBindTexture(GL_TEXTURE_2D, texId);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        glBindFramebuffer(GL_FRAMEBUFFER, workerFrameBuffer);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texId, 0);

        GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
        if ( status == GL_FRAMEBUFFER_COMPLETE ) {

            drawGraphics(&esContext);
            glBindTexture(GL_TEXTURE_2D, 0);
            //glFlush();

            /////////////////////////////////////////////
            //then draw the texture to the main UIView
            /////////////////////////////////////////////
            if (!mainContext || [EAGLContext setCurrentContext:mainContext] == NO) {
                NSLog(@"SwapBuffers: [EAGLContext setCurrentContext:mainContext] failed");
                return;
            }
            glBindTexture(GL_TEXTURE_2D, texId);

            // Set texture parameters
            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);

            glBindFramebuffer(GL_FRAMEBUFFER, mainFrameBuffer);

            status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
            if ( status == GL_FRAMEBUFFER_COMPLETE ) {

                // Draw the texture on the screen with OpenGL ES 2
                drawUIView(&esContext, textureVertices);

                // Present the UIView
                glBindRenderbuffer(GL_RENDERBUFFER, mainColorBuffer);
                [mainContext presentRenderbuffer:GL_RENDERBUFFER];
                glBindTexture(GL_TEXTURE_2D, 0);
            }
            //glFlush();
        }
        //Flush textureCache
        CVOpenGLESTextureCacheFlush(cvTextureCache, 0);

        //Release created texture
        CFRelease(cvTexture);
    }
}

void drawUIView( ESContext *esContext, const GLfloat* textureVertices)
{
    UserData *userData = esContext->userData;
    static const GLfloat squareVertices[] = {
        -1.0f, -1.0f,
        1.0f, -1.0f,
        -1.0f,  1.0f,
        1.0f,  1.0f,
    };

    // Set the view port to the entire view
    glViewport(0, 0, esContext->viewWidth, esContext->viewHeight);

    // Clear the color buffer
    glClear ( GL_COLOR_BUFFER_BIT );

    // Use shader program.
    glUseProgram(userData->passThroughProgram);

    // 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);

    // Update uniform values if there are any
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
///
// Draw a triangle using the shader pair created in Init()
//
void drawGraphics ( ESContext *esContext )
{
    UserData *userData = esContext->userData;
    static const GLfloat vVertices[] = {  0.0f,  0.5f, 0.0f,
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f };

    // Set the viewport
    glViewport ( 0, 0, esContext->bufWidth, esContext->bufHeight );

    // Clear the color buffer
    glClear ( GL_COLOR_BUFFER_BIT );

    // Use the program object
    glUseProgram ( userData->graphicsProgram );

    // Load the vertex data
    glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0, vVertices );
    glEnableVertexAttribArray ( 0 );

    glDrawArrays ( GL_TRIANGLES, 0, 3 );
}



Best Answer-推荐答案


纹理缓存中的像素缓冲区必须与纹理相关联,因此您不能直接将其与 CAEAGLLayer 渲染目标一起使用。

但是,您可以通过将场景渲染到与 CVOpenGLESTextureCache 相关的纹理,然后使用简单的四边形和直通着色器将该纹理渲染到 CAEAGLLayer 中的屏幕,来避免渲染相同的场景两次。这对渲染性能的影响很小,但可以避免使用 glReadPixels() 来提取电影录制的场景信息。

关于ios - 如何在 UIView 和另一个线程之间共享 CVOpenGLESTextureCache?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17842843/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap