El bucle de renderizado de OpenGL ES se coloca en una hebra separada en mi aplicación de iphone. Todo va bien, excepto que el presente método EAGLContextRenderbuffer falla. El resultado es una pantalla blanca en blanco. Cuando se ejecuta el mismo código en el subproceso principal, presentRenderbuffer tiene éxito y los gráficos se muestran correctamente. ¿Cuál es la forma correcta de hacer OpenGL en un hilo separado?¿Cómo usar OpenGL ES en un hilo separado en iphone?
Respuesta
Necesita crear un EAGLSharegroup
.
Consulte this thread sobre cómo compartir contextos OpenGL entre hilos.
ACTUALIZACIÓN
anterior a IOS5 que comparten contextos OpenGL entre hilos para permitir la carga asíncrona de texturas de disco. Pero el CVOpenGLESTextureCaches
de iOS5 básicamente hace que las cargas de texturas sean gratuitas, así que ya no necesito compartir grupos y mi código es más simple y rápido.
No debe representar el contexto en un hilo diferente. En su lugar, haga todos los cálculos en un hilo diferente, y luego asegúrese de que el renderizado ocurra en el hilo de la pantalla principal.
Puede hacerlo muy fácilmente usando GCD. – Cthutu
Gracias, Fistman. Lo hice funcionar y obtuve la ganancia de rendimiento que esperaba al usar un hilo por separado. EAGLSharegroup resolvió el problema.
Creé el contexto para el segundo subproceso como se describe here.
Aquí está el código repetitivo:
#import <UIKit/UIKit.h>
#import <OpenGLES/EAGL.h>
#import <OpenGLES/ES1/gl.h>
#import <OpenGLES/ES1/glext.h>
#import <QuartzCore/QuartzCore.h>
#import <OpenGLES/EAGLDrawable.h>
struct OpenGLContext
{
GLint Width;
GLint Height;
GLuint RenderBuffer;
GLuint FrameBuffer;
GLuint DepthBuffer;
UIView* View;
EAGLContext* MainContext;
EAGLContext* WorkingContext;
EAGLSharegroup* Sharegroup;
// Trivial constructor.
OpenGLContext();
// Call on the main thread before use.
// I call it in layoutSubviews.
// view must not be nil.
void MainInit(UIView* view);
// Call on the rendering thread before use, but
// after MainInit();
void InitOnSecondaryThread();
// Call before any OpenGL ES calls, at the
// beginning of each frame.
void PrepareBuffers();
// Present frame. Call at the end of each
// frame.
void SwapBuffers();
};
OpenGLContext::OpenGLContext()
{
Width = 0;
Height = 0;
RenderBuffer = 0;
FrameBuffer = 0;
DepthBuffer = 0;
View = 0;
MainContext = 0;
WorkingContext = 0;
Sharegroup = 0;
}
void OpenGLContext::InitOnSecondaryThread()
{
EAGLSharegroup* group = MainContext.sharegroup;
if (!group)
{
NSLog(@"Could not get sharegroup from the main context");
}
WorkingContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1 sharegroup:group];
if (!WorkingContext || ![EAGLContext setCurrentContext:WorkingContext]) {
NSLog(@"Could not create WorkingContext");
}
}
void OpenGLContext::MainInit(UIView* view)
{
View = view;
MainContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
if (!MainContext || ![EAGLContext setCurrentContext:MainContext]) {
NSLog(@"Could not create EAGLContext");
return;
}
NSLog(@"Main EAGLContext created");
glGenFramebuffersOES(1, &FrameBuffer);
glGenRenderbuffersOES(1, &RenderBuffer);
glGenRenderbuffersOES(1, &DepthBuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, FrameBuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, RenderBuffer);
if (![MainContext renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)View.layer])
{
NSLog(@"error calling MainContext renderbufferStorage");
return;
}
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, RenderBuffer);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &Width);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &Height);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, DepthBuffer);
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, Width, Height);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, DepthBuffer);
glFlush();
if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
}
WorkingContext = MainContext;
}
void OpenGLContext::PrepareBuffers()
{
if (!WorkingContext || [EAGLContext setCurrentContext:WorkingContext] == NO)
{
NSLog(@"PrepareBuffers: [EAGLContext setCurrentContext:WorkingContext] failed");
return;
}
glBindFramebufferOES(GL_FRAMEBUFFER_OES, FrameBuffer);
}
void OpenGLContext::SwapBuffers()
{
if (!WorkingContext || [EAGLContext setCurrentContext:WorkingContext] == NO)
{
NSLog(@"SwapBuffers: [EAGLContext setCurrentContext:WorkingContext] failed");
return;
}
glBindRenderbufferOES(GL_RENDERBUFFER_OES, RenderBuffer);
if([WorkingContext presentRenderbuffer:GL_RENDERBUFFER_OES] == NO)
{
NSLog(@"SwapBuffers: [WorkingContext presentRenderbuffer:GL_RENDERBUFFER_OES] failed");
}
}
- 1. iphone ios ejecutándose en un hilo separado
- 2. SensorEventListener en un hilo separado
- 3. Cómo usar un hilo separado para realizar solicitudes HTTP
- 4. ¿BeginInvoke() ejecuta un hilo separado?
- 5. ¿Desea actualizar TWebBrowser en un hilo separado?
- 6. ¿Cómo puedo ejecutar un servicio en un hilo separado?
- 7. iPhone OpenGL ES - Cómo elegir
- 8. Cualquier alternativa glPolygonMode en iPhone (OpenGL ES)?
- 9. Ejecutando un formulario Tkinter en un hilo separado
- 10. Correo electrónico en un hilo separado en php
- 11. Colocación de un NSTimer en un hilo separado
- 12. Convolviendo una imagen con OpenGL ES en iPhone: ¿es posible?
- 13. esperando la entrada del usuario en un hilo separado
- 14. OpenGL ES (iPhone) Touch Picking
- 15. iPhone: ¿Cómo determinar si el hilo es el hilo principal?
- 16. Cómo cargar y mostrar imágenes en OpenGL ES para iphone
- 17. Do C# ¿Los temporizadores transcurren en un hilo separado?
- 18. Ejecutar un proceso o hilo por separado en Qt
- 19. OpenGL ES (iPhone) mezcla alfa ve raro
- 20. Cómo ejecutar el método en el hilo separado
- 21. OpenGL ES 1.1 o 2.0 en el iPhone
- 22. Accediendo al control de un formulario desde un hilo separado
- 23. iPhone OpenGL ES 2.0 - Pixel Perfect Textures
- 24. ¿Cómo guardo los archivos en el disco duro en un hilo separado?
- 25. ¿Cómo crear un cuadro de diálogo MFC con una barra de progreso en un hilo separado?
- 26. cómo detener un NSThread sub-hilo en iphone
- 27. ¿Es seguro usar SHFileOperation en un hilo de trabajo?
- 28. ¿Cómo usar OpenGL ES 2.0 en Android SDK (no NDK)?
- 29. ¿Hay algún tutorial sobre cómo cargar un modelo 3D en OpenGL ES en el iPhone?
- 30. Dibujar para renderbuffer fuera de pantalla en OpenGL ES (iPhone)
¿Qué quiere decir con "hacer cargas de texturas gratis"? Intenté llamar a CVOpenGLESTextureCacheCreateTextureFromImage() con un resultado de CVPixelBufferCreateWithBytes() y me llevó el mismo tiempo cargar la textura con glTexImage2D(). – MoDJ
glTexImage2D hace el equivalente de memcpy en una textura, mientras que TextureFromImage apunta la textura a su imagen, no necesita copiar. Puede guardar una gran cantidad de ancho de banda de memoria. El tiempo por sí solo no revelará tanto como GL es asincrónico. Necesita ver el uso de la GPU/CPU y la velocidad de cuadros. –
Consulte http://stackoverflow.com/questions/12813442/cvopenglestexturecache-vs-gltexsubimage2d-on-ios, parece que no funciona de la manera que describe cuando el usuario pasa en un búfer. De hecho, estoy viendo mucho tiempo de CPU gastado en glTexImage2D en esta ruta de ejecución. – MoDJ