Android OpenGL текстуры: создание и удаление их на лету - PullRequest
5 голосов
/ 13 марта 2012

В настоящее время я использую средство трехмерного просмотра, которое в основном отображает подмножество всех изображений, которые пользователь имеет на своей SD-карте. Ближайший подходящий продукт, который я бы думать, было бы CoolIris:

enter image description here

Это просто показать прокрутку доску N плиток на экране, каждый из которых показывают различные изображения, с новой плиткой ввода экрана и показывать новые изображения.

Теперь моя проблема: У меня есть программа, работающая и рендеринга хорошо квадрицепсы. Когда четырехъядерные выходит из экрана, он получает переработан / отпущено. И новые квадроциклы продолжают быть добавлены к плитке плате, прежде чем они попадают на экран.

Поскольку изображения могут быть сотнями, текстуры нужно создавать и удалять на лету (чтобы у нас не хватало памяти). У меня проблема в том, что после удаления текстур вновь созданные текстуры, похоже, получают некоторые идентификаторы других текстур, используемых в настоящее время.

Мой цикл рендеринга выглядит следующим образом:

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

код Texture удаления:

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

Ответы [ 2 ]

5 голосов
/ 14 марта 2012

Я решил проблему: проблема заключалась в том, что вы должны сохранить массив текстур, передаваемый в 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();
4 голосов
/ 20 декабря 2013

Я знаю, что вы сказали, что решили свою проблему, но я думаю, что заметил вашу ошибку в первом бите кода. Посмотрите на цикл while в вашем коде удаления текстуры, вы не увеличиваете индекс i для своего массива, поэтому вы будете непрерывно присваивать первый индекс, пока не достигнете последней записи в pendingTextureUnloads, остальные индексы будут равны 0 (пусто) , Это может быть проблематично.

И, кстати, у меня работает генерация текстур, я не использую массив, просто возвращаю индекс, сгенерированный glGenTextures. Мой код соответствует строке, отличной от вашей, за исключением создания нового массива int в начале метода и возврата int в первом индексе в конце. Ваш код для генерации текстуры должен работать, ошибка была только в удалении текстуры.

...