2012-03-13 41 views
5

我目前正在實現一個3D查看器,它基本上呈現用戶在其SD卡上的所有圖像的子集。最匹配的產品,我覺得將是Cooliris的:Android OpenGL紋理:在飛行中創建和刪除它們

enter image description here

它只是在屏幕上顯示N個片區的滾動板,分別表示不同的圖像,用新的瓷磚進入屏幕,並顯示新的圖像。

現在爲我的問題:我有程序工作,並呈現很好的四邊形。當四分之一畫面離開屏幕時,它會被回收/釋放。新的四邊形在進入屏幕前繼續添加到瓷磚板上。

因爲可以有數百個圖像,所以需要動態地創建和刪除紋理(以便我們不會耗盡內存)。我遇到的問題是,在刪除紋理之後,新創建的紋理似乎會獲得當前正在使用的其他紋理的一些ID。

我的渲​​染循環是這樣的:

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) 

} 

舉的數據是如何組織一個更好的主意,這裏是類的概述:

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

Tile { 
    Image image; 
} 

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

紋理創建代碼:

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 2012-03-13 16:26:57

回答

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-dim數組生成紋理時,我看到了很多其他示例。另外,你是否在調用glGenTextures之前不啓動數組? – 2013-10-04 18:20:03

4

我知道你說你解決了你的問題,但我想我注意到你在第一個代碼中的錯誤。看看你的紋理刪除代碼中的while循環,你不會增加你的數組的索引i,所以你會連續分配第一個索引,直到你到達pendingTextureUnloads中的最後一個條目,剩下的索引將是0(空) 。這可能有問題。

順便說一下,我通過不重複使用數組來獲得紋理生成,只是返回由glGenTextures生成的索引。我的代碼是等於你的行,除了在方法開始時創建一個新的int數組並在結尾的第一個索引處返回int。你的紋理生成代碼應該可以工作,錯誤只是在紋理刪除。

+0

好的。 +1 :) – 2014-01-06 17:38:01