高度な検索
Developer Connection
Member Login ログイン | ご入会 ADC連絡先

Technical Q&A QA1325
Creating an OpenGL texture from an NSView


Q: NSView から OpenGL テクスチャを作成するにはどうすればよいのでしょうか。

A: ほとんどすべての NSView およびそのサブクラスを OpenGL でテクスチャとして使用できます。その基本プロセスには、NSBitmapImageRep を使用して NSView のイメージデータを OpenGL でテクスチャデータとしてすぐに使用できる形式で格納することが含まれます。次の手順でこの方法をより詳細に規定します。

  • NSBitmapImageRep をテクスチャデータの格納に使用するために割り当てます。
  • -initWithFocusedViewRect: メソッドと NSView -bounds メソッドを使用して、NSBitmapImageRep を初期化します。
  • NSBitmapImageRep メソッドの -bitmapData を使用して実際のピクセルデータを取り出し、これを OpenGL に、適切なパラメータとともにテクスチャとして渡します。

リスト 1 は、実際にこのテクニックを使用する自己完結型 Cocoa メソッドを示しています。

リスト 1. NSView からの OpenGL テクスチャの作成

// 現在の OpenGL コンテキスト内の 'theView' から 'texName' テクスチャを生成
-(void)textureFromView:(NSView*)theView textureName:(GLuint*)texName
{
    // ソースビューからビットマップを生成
    NSBitmapImageRep * bitmap = [NSBitmapImageRep alloc];
    int samplesPerPixel = 0;
    
    [theView lockFocus];
    [bitmap initWithFocusedViewRect:[theView bounds]];
    [theView unlockFocus];

    // 読み取るビットマップの適切な行の長さを設定
    glPixelStorei(GL_UNPACK_ROW_LENGTH, [bitmap pixelsWide]);

    // 読み取る配列のバイト数を設定 (ビットマップのピクセルあたり 3 バイト必要)
    glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
    // テクスチャが渡されない場合は、新しいテクスチャオブジェクトを生成
    if (*texName == 0)
         glGenTextures (1, texName);
     glBindTexture (GL_TEXTURE_RECTANGLE_EXT, *texName);
    // ミップマップなしのフィルタ処理 (texture_rectangle には冗長)
    glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, 
                    GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    samplesPerPixel = [bitmap samplesPerPixel];

    // 非 Planer、RGB 24 ビットビットマップ、または RGBA 32 ビットビットマップ
    if(![bitmap isPlanar] && 
       (samplesPerPixel == 3 || samplesPerPixel == 4)) { 
         glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 
                      0, 
                      samplesPerPixel == 4 ? GL_RGBA8 : GL_RGB8,
                      [bitmap pixelsWide], 
                      [bitmap pixelsHigh], 
                      0, 
                      samplesPerPixel == 4 ? GL_RGBA : GL_RGB,
                      GL_UNSIGNED_BYTE, 
                      [bitmap bitmapData]);
    } else {
    /*
        エラー状態...
        上のコードでは 2 つのケース (24 ビット RGB、および 32 ビット RGBA) が処理されており、
        必要であれば、ほかのビットマップ形式のサポートも可能。
        
        いくつかの有用な情報をログに書き出す。
    */
        NSLog (@"-textureFromView: Unsupported bitmap data
        format: isPlanar:%d, samplesPerPixel:%d, bitsPerPixel:%d,
        bytesPerRow:%d, bytesPerPlane:%d",
            [bitmap isPlanar], 
            [bitmap samplesPerPixel], 
            [bitmap bitsPerPixel], 
            [bitmap bytesPerRow], 
            [bitmap bytesPerPlane]);
    }
    // クリーンアップ処理
    [bitmap release];
}

上のコードを検討する際、以下の点に注意する必要があります。

  • GL_EXT_texture_rectangle は、Rage128 でサポートされていない、2 つのテクスチャをサポートするために使用されます。
  • gluScaleImage() は、GL_EXT_texture_rectangle をサポートしないハードウェア用に、非 PoT テクスチャを PoT サイズへスケール処理するために使用できます。
  • 有効な現在の OpenGL コンテキストが必要です。
  • この種類の操作では、機能しないビューがあります。現時点では、これらのビューには NSProgressIndicatorNSMovieViewNSOpenGLView があります。initWithFocusedViewRect: は、これらのビューが使用しない、ウインドウバッキングストアから読み込まれます。描画に別のサーフェスを使用するこれらのビューは、initWithFocusedViewRect: には読み取れません。

[2004 年 2 月 13 日]