菜鸟教程小白 发表于 2022-12-12 12:54:42

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


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

<p>根据线程:<a href="https://stackoverflow.com/questions/1253145/how-to-use-opengl-es-on-a-separate-thread-on-iphone" rel="noreferrer noopener nofollow">How to use OpenGL ES on a separate thread on iphone?</a> </p>

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

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

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

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

<p>提前致谢。</p>

<p>问候,霍华德</p>

<p>===========更新========</p>

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

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

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

<p>非常感谢!</p>

<p>下面是我的代码:</p>

<pre><code>//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,
                                                                &amp;cvTexture);
    if (err == kCVReturnSuccess) {
      assert(CVOpenGLESTextureGetTarget(cvTexture) == GL_TEXTURE_2D);
      GLint texId = CVOpenGLESTextureGetName(cvTexture);
      if (!workingContext || == NO) {
            NSLog(@&#34;SwapBuffers: failed&#34;);
            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(&amp;esContext);
            glBindTexture(GL_TEXTURE_2D, 0);
            //glFlush();

            /////////////////////////////////////////////
            //then draw the texture to the main UIView
            /////////////////////////////////////////////
            if (!mainContext || == NO) {
                NSLog(@&#34;SwapBuffers: failed&#34;);
                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(&amp;esContext, textureVertices);

                // Present the UIView
                glBindRenderbuffer(GL_RENDERBUFFER, mainColorBuffer);
                ;
                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-&gt;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-&gt;viewWidth, esContext-&gt;viewHeight);

    // Clear the color buffer
    glClear ( GL_COLOR_BUFFER_BIT );

    // Use shader program.
    glUseProgram(userData-&gt;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-&gt;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-&gt;bufWidth, esContext-&gt;bufHeight );

    // Clear the color buffer
    glClear ( GL_COLOR_BUFFER_BIT );

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

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

    glDrawArrays ( GL_TRIANGLES, 0, 3 );
}
</code></pre></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>纹理缓存中的像素缓冲区必须与纹理相关联,因此您不能直接将其与 CAEAGLLayer 渲染目标一起使用。 </p>

<p>但是,您可以通过将场景渲染到与 CVOpenGLESTextureCache 相关的纹理,然后使用简单的四边形和直通着色器将该纹理渲染到 CAEAGLLayer 中的屏幕,来避免渲染相同的场景两次。这对渲染性能的影响很小,但可以避免使用 <code>glReadPixels()</code> 来提取电影录制的场景信息。</p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 如何在 UIView 和另一个线程之间共享 CVOpenGLESTextureCache?,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/17842843/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/17842843/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 如何在 UIView 和另一个线程之间共享 CVOpenGLESTextureCache?