这是节奏拳手或任何知道答案的人的问题:
根据线程: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-推荐答案 strong>
纹理缓存中的像素缓冲区必须与纹理相关联,因此您不能直接将其与 CAEAGLLayer 渲染目标一起使用。
但是,您可以通过将场景渲染到与 CVOpenGLESTextureCache 相关的纹理,然后使用简单的四边形和直通着色器将该纹理渲染到 CAEAGLLayer 中的屏幕,来避免渲染相同的场景两次。这对渲染性能的影响很小,但可以避免使用 glReadPixels() 来提取电影录制的场景信息。
关于ios - 如何在 UIView 和另一个线程之间共享 CVOpenGLESTextureCache?,我们在Stack Overflow上找到一个类似的问题:
https://stackoverflow.com/questions/17842843/
|