我为文字游戏创建了动态纹理,并保留在FrameBuffer上。然后,我使用该FrameBuffer支持的TextureRegions绘制到屏幕上。这段代码在Android上运行良好,但在iOS上却遇到问题。

您可以在下面的屏幕截图中看到,在左下方绘制了FrameBuffer内容-一切都很好。



但是,如果返回到iOS主屏幕,则会丢弃FrameBuffer,然后根据需要重新创建所有内容并将其重新绘制到FrameBuffer。然后,FrameBuffer的内容似乎是屏幕的部分翻转镜像。



我尝试在每个帧上放置并重新创建FrameBuffer,以查看会发生什么。同样,除非我返回iOS主屏幕,否则此方法非常有效,此后FrameBuffer的内容不正确。

然后,我尝试减小FrameBuffer的大小并绘制多个FrameBuffers。如果执行此操作,除非返回到iOS主屏幕,否则它仍然可以正常工作。但是,在这种情况下,只有创建的第一个FrameBuffer损坏,所有后续缓冲区都可以。



然后,我尝试始终先创建一个1x1px FrameBuffer,再也不要画任何东西,这解决了我的问题....但是为什么!看来我从iOS主屏幕返回后创建的第一个FrameBuffer不能按预期工作,但是此后的每个FrameBuffer都可以。似乎总是试图在我创建的第一个FrameBuffer上绘制屏幕。

FrameBuffer的创建和绘制代码如下:

private static FrameBuffer getFrameBuffer(boolean newRequired) {
    if (newRequired || frameBuffers.size == 0) {
        FrameBuffer frameBuffer;

        try {
            frameBuffer = new FrameBuffer(Pixmap.Format.RGBA8888, getFrameBufferSize(), getFrameBufferSize(), false);
        } catch (Exception e) {
            frameBuffer = new FrameBuffer(Format.RGBA4444, getFrameBufferSize(), getFrameBufferSize(), false);
        }

        frameBuffer.begin();
        Gdx.gl20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT);
        frameBuffer.end();

        frameBuffers.add(frameBuffer);

        // Set up the camera correctly for the frame buffer
        OrthographicCamera camera = new OrthographicCamera(frameBuffer.getWidth(), frameBuffer.getHeight());
        camera.position.set(frameBuffer.getWidth() * 0.5f, frameBuffer.getHeight() * 0.5f, 0);
        camera.update();
        spriteBatch.setProjectionMatrix(camera.combined);
    }

    return frameBuffers.get(frameBuffers.size - 1);
}

private static TextureRegion getTextureUsingGpu(String letter, Bubble.BubbleType bubbleType) {
    if (!enabled)
        return null;

    TextureRegion tx = getBlockImage(letter, bubbleType);

    int width = (int) (tx.getRegionWidth() * LayoutManager.getShortEdge() / 1080 * LayoutManager.getScaling());
    int height = (int) (tx.getRegionHeight() * LayoutManager.getShortEdge() / 1080 * LayoutManager.getScaling());

    if (nextTextureX + width + PADDING > getFrameBufferSize()) {
        nextTextureX = PADDING;
        nextTextureY = nextRowY + PADDING;
        if (nextTextureY + height + PADDING > getFrameBufferSize()) {
            getFrameBuffer(true);
            nextRowY = PADDING;
            nextTextureY = PADDING;
        }
    }

    FrameBuffer fb = getFrameBuffer(false);

    fb.begin();
    spriteBatch.begin();

    tx.flip(false, !tx.isFlipY());

    spriteBatch.disableBlending();
    spriteBatch.draw(tx, nextTextureX, nextTextureY, width, height);
    spriteBatch.enableBlending();

    // Drawing Code Removed

    spriteBatch.end();
    fb.end();

    TextureRegion textureRegion = new TextureRegion(fb.getColorBufferTexture(), nextTextureX, nextTextureY, width, height);
    textureRegion.getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);
    cacheTexture(letter, textureRegion);

    nextTextureX += width;
    nextRowY = Math.max(nextRowY, nextTextureY + height);

    return textureRegion;
}

最佳答案

如果要从getFrameBuffergetTextureUsingGpu方法调用resizeresume,那就是问题所在。在iOS上,不一定要在OpenGL准备恢复之前调用resizeresume,因此在该处执行与OpenGL直接相关的任何操作都是不安全的,例如创建ShaderPrograms,加载纹理或创建FrameBuffers。我在游戏中通过使用resume设置成员布尔值来解决此问题,并使用该值将新帧缓冲区的创建推迟到render方法。

关于ios - iOS上的LibGDX FrameBuffer怪癖,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30047801/

10-13 04:01