简体   繁体   English

OpenGL ES异步纹理加载

[英]OpenGL ES Async texture loading

Simple question, is it possible to load texture asynchronously with iOS and OpenGL ES ? 简单的问题是,是否可以与iOS和OpenGL ES异步加载纹理?

Here is my loading method, called on a separate thread: 这是我的加载方法,在一个单独的线程上调用:

//Image size
GLuint width = CGImageGetWidth(image.CGImage);
GLuint height = CGImageGetHeight(image.CGImage);

//Create context
void *imageData = malloc(height * width * 4);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(imageData, width, height, 8, 4 * width, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);

//Prepare image
CGContextClearRect(context, CGRectMake(0, 0, width, height));
CGContextDrawImage(context, CGRectMake(0, 0, width, height), image.CGImage);

//Dispatch OpenGL stuff on main thread
dispatch_sync(dispatch_get_main_queue(), ^{
    //Bind texture
    glBindTexture(GL_TEXTURE_2D, name);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
});

//Release
CGContextRelease(context);
free(imageData);

If I don't dispatch OpenGL calls on the main thread, my textures wont be displayed... 如果我不在主线程上调度OpenGL调用,我的纹理将不会显示...

Same question for the glDeleteTextures call... glDeleteTextures调用的同样问题......

Any idea ? 任何想法 ?

You need to use the same context on your background thread that you're using on the main one. 您需要在主要背景线程上使用相同的上下文。 For this use setCurrentContext: . 为此使用setCurrentContext : . So on main thread create new thread (as an example the simplest way) and pass main context 所以在主线程上创建新线程(作为一个例子,最简单的方法)并传递主上下文

[self performSelectorInBackground: @selector(loadTextureWithContext:) withObject: [EAGLContext currentContext]];

And the creation code: 而创作代码:

-(void) loadTextureWithContext:(EAGLContext*) main_context {
    [EAGLContext setCurrentContext: main_context];

    //Image size
    GLuint width = CGImageGetWidth(image.CGImage);
    GLuint height = CGImageGetHeight(image.CGImage);

    //Create context
    void *imageData = malloc(height * width * 4);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(imageData, width, height, 8, 4 * width, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGColorSpaceRelease(colorSpace);

    //Prepare image
    CGContextClearRect(context, CGRectMake(0, 0, width, height));
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), image.CGImage);

    //Bind texture
    glBindTexture(GL_TEXTURE_2D, name);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    //Release
    CGContextRelease(context);
    free(imageData);

    [EAGLContext setCurrentContext: nil];
}

As an option you can also create the new context and share the same EAGLSharegroup with the main one. 作为选项,您还可以创建新上下文并与主要上下文共享相同的EAGLSharegroup

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM