经常切换到另一个纹理会破坏游戏

时间:2014-12-27 04:40:01

标签: android opengl-es textures

我使用Open GL ES(1.1)为Android做了一个非常漂亮的测试游戏。为了简单和方便处理纹理,我使用包含以下方法的类来封装必要的gl-operations(在代码中我使用了一些自己的附加类):

public void load() {
    GL10 gl = glGraphics.getGL();
    int[] textureIds = new int[1];
    gl.glGenTextures(1, textureIds, 0);
    textureId = textureIds[0];
    InputStream in = null;
    try {
        in = fileIO.readAsset(fileName);
        Bitmap bitmap = BitmapFactory.decodeStream(in);
        gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);
        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
        gl.glBindTexture(GL10.GL_TEXTURE_2D, 0);
        bitmap.recycle();
    }
    catch(IOException e) {
        throw new RuntimeException("Couldn't load texture '" + fileName + "'", e);
    }
    finally
    {
        if(in != null)
        {
            try {
                in.close();
            }
            catch (IOException e) { }
        }
    }
}

public void reload() {
    load();
    setFilters(minFilter, magFilter);
    glGraphics.getGL().glBindTexture(GL10.GL_TEXTURE_2D, 0);
}

public void setFilters(int minFilter, int magFilter) {
    this.minFilter = minFilter;
    this.magFilter = magFilter;
}

public void bind() {
    GL10 gl = glGraphics.getGL();
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, minFilter);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, magFilter);
}

public void dispose() {
    GL10 gl = glGraphics.getGL();
    gl.glBindTexture(GL10.GL_TEXTURE_2D, 0);
    int[] textureIds = { textureId };
    gl.glDeleteTextures(1, textureIds, 0);
}

开始使用一些纹理我加载()它。当我想绘制一个精灵时,我使用方法bind()作为纹理。当上下文可能丢失时,我使用方法reload()。当我对纹理说再见时,我称之为dispose()。

我同时使用两个纹理图集1136 x 640(其中一个包含播放元素,另一个包含背景)。为了避免无聊,当用户离开开始游戏菜单并再次进入游戏本身时,地图集会切换到两个类似的地图集以其他方式着色。

问题在于,如果用户经常这样做,那么每次游戏加载越来越慢,并且几次(5-7)崩溃。处理方法及时工作,整个类的方法finalize()及时工作。

你有什么想法吗?

1 个答案:

答案 0 :(得分:0)

很难说你给出的信息,但你可能已经没有记忆了。你在这个过程中是否正在调用reload()方法?我注意到的一件事是你的reload()方法将创建一个全新的纹理副本,而不会删除以前的副本。

总结:确保对glGenTextures的每次通话与对glDeleteTextures的通话配对。对重载方法的一个简单但缓慢的修复方法是:

public void reload() {
   // call dispose() before load()
   dispose();
   load();
   // ...
}

但更安全的解决方法是,如果再次调用load(),只需替换先前分配的纹理的内容。在load()方法中,如果已分配纹理Id,则跳过对glGenTextures的调用。像这样:

// initialize texture id
private int textureId = 0;

public void load() {
   // ...

   // only allocate texture if needed
   if (textureId == 0) {
      int[] textureIds = new int[1];
      gl.glGenTextures(1, textureIds, 0);
      textureId = textureIds[0];
   }

   // ...
}

public void dispose() {
   // ...

   // delete texture if allocated, and
   // set the id to zero
   if (textureId != 0) {
      int[] textureIds = { textureId };
      gl.glDeleteTextures(1, textureIds, 0);
      textureId = 0;
   }

   // ...
}

我还建议尝试使用两种纹理(即1024x512而不是1136x640)。我已经看到一些芯片/驱动程序存在非POT纹理的无证问题。