2012-03-13 25 views
5

Şu anda kullanıcının SD Kartında bulunan tüm görüntülerin bir alt kümesini oluşturan bir 3B görüntüleyici uyguluyor. Ben düşünürdüm yakın eşleşen ürün Cooliris'i olacaktır:Android OpenGL dokular: anında oluşturma ve silme

enter image description here

Bu sadece her yeni fayans ekranına girip yeni görüntüler gösteren ile farklı görüntüler gösteren ekranda N karoların bir kaydırma kurulu göstermektedir.

Şimdi benim problemim için: Programın dörtlüleri güzelce çalışmasına ve oluşturmasına sahibim. Dörtlü ekrandan çıktığında, geri dönüştürülür/bırakılır. Ve yeni dörtlü ekrana girmeden önce kiremit panosuna eklenmeye devam ediyor.

Yüzlerce resim olabileceğinden, dokular uçta oluşturulmalı ve silinmelidir (böylece bellek tükenmez). Sahip olduğum problem, dokuları sildikten sonra, yeni oluşturulan dokuların şu anda kullanımda olan bazı dokulardan bazılarının kimliklerini almasıdır.

Benim render döngü şöyle görünür:

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

Tile { 
    Image image; 
} 

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

Doku oluşturma kodu:

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) 

} 

veri nasıl düzenlendiğini daha iyi bir fikir vermek için, burada sınıfların bir bakış

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

Doku silme kodu:

// 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'u herhangi bir yerde arayarak mı denediniz? – Tim

cevap

5

Sorunu çözdüm: sorun, doku dizisini glGenTextures'a geçirip yeniden kullanmanız gerektiğiydi.

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

Doku oluşturma kodu:

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

Doku silme kodunu: Biliyorum

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

Birinin tüm bunların nasıl çalıştığını ve bu durumda neden aynı dizinin kullanılmasının gerektiğini bilmek güzel olurdu. Dokular çoklu 1 boyutlu diziler kullanılarak oluşturulduğunda birçok örnek gördüm. Ayrıca, glGenTextures çağırmadan önce diziyi başlatmıyor musunuz? –

4

İşte

aynı sorun var olacak olanlar için modifiye bakıştır Sorununuzu çözdüğünüzü söylediniz, ama sanırım ilk koddaki hatayı fark ettim. Doku silme kodunuzdaki while döngüsüne bakın, diziniz için i indeksini yükseltmiyorsunuz, böylece pendingTextureUnloads içinde son girdiye ulaşana kadar ilk dizini sürekli atayacaksınız, dizinlerin geri kalanı 0 (null) olacak . Bu sorunlu olabilir.

Ve bu arada, ben dizi yeniden kullanma değil, glGenTextures tarafından oluşturulan indeks döndürerek çalışan bir doku üretimi var. Kodum, yöntemin başlangıcında yeni bir int dizisi oluşturmak ve int'deki ilk dizinde int döndürmek dışında sizinkiyle eşittir. Doku üretimi için kodunuz çalışmalı, hata sadece doku silme işlemindeydi.

+0

İyi yakalama. +1 :) –