【问题标题】:OpenGL ES Async texture loadingOpenGL ES 异步纹理加载
【发布时间】:2011-08-01 14:02:58
【问题描述】:

简单的问题,是否可以使用 iOS 和 OpenGL ES 异步加载纹理?

这是我的加载方法,在单独的线程上调用:

//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);

如果我不在主线程上调度 OpenGL 调用,我的纹理将不会显示...

glDeleteTextures 调用的相同问题...

有什么想法吗?

【问题讨论】:

    标签: ios opengl-es asynchronous


    【解决方案1】:

    您需要在后台线程上使用与主线程相同的上下文。为此使用setCurrentContext:。 所以在主线程上创建新线程(例如最简单的方法)并传递主上下文

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

    以及创建代码:

    -(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];
    }
    

    作为一个选项,您还可以创建新上下文并与主上下文共享相同的EAGLSharegroup

    【讨论】:

    • 我想知道用于创建纹理的 glBindTexture() 调用是否不会破坏您可能在主线程中执行的任何绘图?我想共享组(= 单独的 gl 上下文)是要走的路?
    • @ranReloaded 如果您正在破坏当前用于渲染的纹理,它可能会中断绘图。
    • 不,我的意思是:在纹理创建过程中,在后台线程(加载纹理的那个)中调用 glBindTexture() 的那一刻,无论(先前创建的,完全加载的)纹理您当前用于绘图(在主线程中)未绑定(您一次只能将一个纹理绑定到任何给定的上下文,对吗?)
    • 换句话说:如果您想在主线程中继续进行纹理映射渲染,同时在后台线程中异步加载纹理,则必须使用共享组链接的两个不同的openGL上下文;单一的上下文不会削减它。如果我错了,请纠正我。
    猜你喜欢
    • 2012-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多