2

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

根据线程:如何在 iphone 上的单独线程上使用 OpenGL ES?

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)Draw:(CVPixelBufferRef)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 );
}
4

1 回答 1

1

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

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

于 2013-07-24T19:35:50.030 回答