12
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

iOSでテクスチャの非同期読み込み

Last updated at Posted at 2014-03-27

サイズの大きいテクスチャを読み込む画面がある場合に、全てのテクスチャの準備が出来てから画面を表示するとレスポンスが遅くなる。
このような場合に別スレッドでテクスチャをロードしつつ、用意のできた部分から使うことにより画面のレスポンスを改善する方法がある。

ただし、各スレッドはデフォルトで異なる OpenGL ES レンダリングコンテキストを持つため、
異なるスレッドで確保したテクスチャを使う場合は、各スレッドで使用する EAGLContext から EAGLShareGroup を共有する必要がある。
これを行うには EAGLContext 生成時に initWithAPI:sharegroup: で元スレッドの sharedGroup を渡す。

AsyncSample.m


- (id)init
{
    // ... (略)
    // 非同期読み込み. EAGLContext を渡す.
    [self performSelectorInBackground:@selector(loadTexture:) withObject:[EAGLContext currentContext]];
    // ... (略)
}

// バックグラウンドスレッドで呼ばれるメソッド.
- (void)loadTexture:(EAGLContext *)ctx;
{
    // sharegroup を指定して異なるコンテクストのリソースを共有する.
    EAGLContext* myContext = [[EAGLContext alloc] initWithAPI:[ctx API]
                                                   sharegroup:[ctx sharegroup]];
    // EAGLContext を設定
    [EAGLContext setCurrentContext:myContext];
    NSArray *imageNames = @[@"image1.png", @"image2.png", @"image3.png"];
    glFlush(); // glFlush を呼び出してコマンドを反映させる.
    for (NSString *imageName in imageNames) {
        GLuint tex = [self createTextureFromUIImage:[UIImage imageNamed:imageName]];
        dispatch_async(dispatch_get_main_queue(), ^{
            // スレッド間共有変数への書き込みは競合を起こさないよう main スレッドで実行.
            self.textures[i] = tex;
        });
    }
}


// UIImage からテクスチャの作成.
- (GLuint)createTextureFromUIImage:(UIImage *)teximage
{
    CGImageRef textureImage = teximage.CGImage;
    NSInteger texWidth = CGImageGetWidth(textureImage);
    NSInteger texHeight = CGImageGetHeight(textureImage);
    GLubyte *textureData = (GLubyte *)malloc(texWidth * texHeight * 4);
    CGContextRef textureContext = CGBitmapContextCreate(textureData,
                                                        texWidth,
                                                        texHeight,
                                                        8, texWidth * 4,
                                                        CGImageGetColorSpace(textureImage),
                                                        kCGImageAlphaPremultipliedLast);
    CGContextDrawImage(textureContext, CGRectMake(0.0, 0.0, (float)texWidth, (float)texHeight), textureImage);
    CGContextRelease(textureContext);
    
    GLuint texid;
    glGenTextures(1, &texid);
    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);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);    
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA,GL_UNSIGNED_BYTE, textureData);
    free(textureData);
    return texid;
}
12
11
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?