You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

OpenGL ES 1.0 Android纹理释放:dispose绑定纹理是否合理?

OpenGL ES 1.0 Texture Disposal & FBO Questions

Hey there! Let's work through your questions step by step—since you're following Mario Zechner's book, you're already on a solid path for Android game dev.

1. Texture Disposal: Bind Before Delete vs. Bind to 0

First, let's clear up the confusion around the dispose() method in the book's Texture class. The code calls glBindTexture(GL10.GL_TEXTURE_2D, textureId) right before glDeleteTextures—here's what's going on:

  • Is this necessary? Short answer: No. OpenGL ES 1.0 allows you to delete a texture ID regardless of whether it's currently bound to a texture target. The glDeleteTextures function just marks the texture memory for release by the GPU driver (as long as no other references to the ID exist, like being attached to an FBO).

  • Why does the book do it? It's probably a redundant step, but it doesn't hurt. Some developers might do this out of habit, or to ensure the texture is the "active" one before deletion—though OpenGL doesn't require it.

  • What about binding to 0 first? Binding GL_TEXTURE_2D to 0 just unbinds whatever texture was currently attached to that target. If you do this before deletion, it ensures the deleted texture isn't left as the active texture for subsequent operations. But even if you don't, deleting a bound texture will automatically unbind it from the target (the target will effectively point to nothing, same as binding 0).

  • How to confirm GPU memory is released? Stopping texture drawing only tells you the texture ID is no longer valid, not that memory is freed. To verify, use Android's built-in tools:

    • Open Android Studio Profiler and switch to the GPU tab—watch for a drop in memory usage after calling dispose().
    • Use adb shell dumpsys gfxinfo to check GPU memory stats before and after disposal.

Your tests (binding 0 or removing the bind call entirely) are valid—either way, the texture ID is invalidated, so drawing stops. The key is that glDeleteTextures is called correctly, which triggers the GPU to release the memory once it's safe.

2. What is an FBO?

FBO stands for Framebuffer Object, and it's an extension-based feature in OpenGL ES 1.0 (via GL_OES_framebuffer_object) for off-screen rendering. Here's the breakdown:

  • By default, OpenGL renders to the default framebuffer, which is tied to your device's screen. An FBO lets you render to a custom buffer instead—usually a texture or a renderbuffer object.
  • Common use cases:
    • Render-to-texture: Draw a scene to a texture, then use that texture as a material on another object (e.g., mirrors, dynamic in-game UI elements).
    • Post-processing: Apply effects like blur, color grading, or bloom by rendering the scene to a texture, then drawing that texture with a shader that applies the effect.
    • Off-screen calculations: Generate textures or visual data without showing anything directly to the user.

In ES 1.0, you'll first need to check if the device supports the FBO extension, then use functions like glGenFramebuffersOES(), glBindFramebufferOES(), and glFramebufferTexture2DOES() to set up and attach textures to your custom framebuffer.

Book's Texture Class Code

Here's the original Texture class from the book, formatted for clarity:

public class Texture {
    GLGraphics glGraphics;
    FileIO fileIO;
    String fileName;
    int textureId;
    int minFilter;
    int magFilter;

    public Texture(GLGame glGame, String fileName) {
        this.glGraphics = glGame.getGLGraphics();
        this.fileIO = glGame.getFileIO();
        this.fileName = fileName;
        load();
    }

    private 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);
            setFilters(GL10.GL_NEAREST, GL10.GL_NEAREST);
            gl.glBindTexture(GL10.GL_TEXTURE_2D, 0);
        } 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();
        bind();
        setFilters(minFilter, magFilter);
        glGraphics.getGL().glBindTexture(GL10.GL_TEXTURE_2D, 0);
    }

    public void setFilters(int minFilter, int magFilter) {
        this.minFilter = minFilter;
        this.magFilter = magFilter;
        GL10 gl = glGraphics.getGL();
        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 bind() {
        GL10 gl = glGraphics.getGL();
        gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);
    }

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

内容的提问来源于stack exchange,提问作者Yesyoor

火山引擎 最新活动