2012-03-13 15 views
5

現在、3Dビューアを実装しています。これは基本的に、ユーザーが自分のSDカードにあるすべての画像のサブセットをレンダリングします。私が思うだろう最も一致する製品はCoolirisのようになります:Android OpenGLテクスチャ:オンザフライでの作成と削除

enter image description here

これは単に、新しいタイルが画面に入って、新しい画像を表示し、それぞれ示す異なる画像、画面上のNタイルのスクロールボードを示しています。

私の問題のために:私はプログラムをうまく動作させ、クワッドをレンダリングしています。クワッドがスクリーンから出ると、それはリサイクル/リリースされます。そして、新しいクワッドは、スクリーンに入る前にタイルボードに追加され続けます。

何百もの画像が存在する可能性があるため、テクスチャを即座に作成して削除する必要があります(メモリが不足しないように)。私が持っている問題は、テクスチャを削除した後、新しく作成されたテクスチャは、現在使用中の他のテクスチャのIDを取得するように見えるということです。

私のレンダリングループは次のようになります。

TileBoard { 
    Image[] allImages; 
    Tile[] board; 
} 

Tile { 
    Image image; 
} 

Image { 
    String path; 
    int textureId; 
    int referenceCount; 
} 

テクスチャ作成コード:

void render(GL10 gl) { 
    0. Move the camera 

    // Tile board maintenance 
    1. Remove tiles out of screen 
    2. Add new tiles which are about to enter screen 

    // Texture handling 
    3. glDeleteTextures on all unused textures followed by glFlush 
    4. For newly used images 
    - Create corresponding Bitmap 
    - Create the OpenGL texture, followed by glFlush 
    - Release the Bitmap 

    // Rendering 
    5. Render the tile (using a textured quad) 

} 

は、データの編成方法の良いアイデアを与えるために、ここでのクラスの概要は、

protected void loadSingleTexture(GL10 gl, long objectId, Bitmap bmp) { 
    int[] textures = new int[1]; 
    gl.glGenTextures(1, textures, 0); 
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); 
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); 
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); 
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0); 
    gl.glFlush(); 

    if (bmp != null) bmp.recycle(); 

    if (listener != null) listener.onTextureLoaded(gl, objectId, textures[0]); 
} 

テクスチャ削除コード:

// pendingTextureUnloads is a Set<Integer> 
if (pendingTextureUnloads.size() > 0) { 
    int[] textureIds = new int[pendingTextureUnloads.size()]; 
    int i = 0; 
    Iterator<Integer> it = pendingTextureUnloads.iterator(); 
    while (it.hasNext()) { 
    textureIds[i] = it.next(); 
    } 

    gl.glDeleteTextures(textureIds.length, textureIds, 0); 
    gl.glFlush(); 
} 
+0

どこでもglGetErrorを呼び出そうとしましたか? – Tim

答えて

5

私は問題を解決しました。問題は、テクスチャ配列をglGenTexturesに渡して、それを再利用する必要があることでした。ここで

は同じ問題を抱えているだろうもののために変更の概要です:

Image { 
    String path; 
    int[] textureIds; 
    int referenceCount; 
} 

テクスチャ作成コード:

// Notice that I don't allocate the int[] at the beginning but use the one of the image 
protected void loadSingleTexture(GL10 gl, Image img, Bitmap bmp) { 
    gl.glGenTextures(1, img.textureIds, 0); 
    gl.glBindTexture(GL10.GL_TEXTURE_2D, img.textureIds[0]); 
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); 
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); 
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0); 
    gl.glFlush(); 

    if (bmp != null) bmp.recycle(); 
} 

テクスチャの削除コード:

foreach Image img { 
    gl.glDeleteTextures(img.textureIds.length, img.textureIds, 0); 
} 
gl.glFlush(); 
+0

誰かがこのすべての仕組みを詳しく知っていて、同じアレイをこの場合に使用しなければならない理由が分かっているといいでしょう。テクスチャが複数の1次元配列を使用して生成されたとき、私は他の多くの例を見てきました。また、glGenTexturesを呼び出す前に配列を初期化しないでください。 –

4

私が知っていますあなたはあなたの問題を解決したと言いましたが、私は最初のコードでエラーに気付いたと思います。テクスチャ削除コードのwhileループを見て、配列のインデックスiを増やしていないので、pendingTextureUnloadsの最後のエントリに到達するまで最初のインデックスを割り当て続け、残りのインデックスは0(NULL)になります。 。それは問題になるかもしれません。

そして、glGenTexturesで生成されたインデックスを返すだけで、配列を再利用しないことでテクスチャの生成が可能になりました。私のコードは、メソッドの先頭に新しいint配列を作成し、最後の最初のインデックスにintを返すことを除いて、あなたと同じ行になります。テクスチャ生成のコードが機能するはずですが、エラーはテクスチャの削除だけです。

+0

良いキャッチ。 +1 :) –

関連する問題