libgdx嵌套帧缓冲区

libgdx嵌套帧缓冲区,libgdx,glsl,game-engine,framebuffer,Libgdx,Glsl,Game Engine,Framebuffer,我在LevelScreen渲染方法中使用FBO渲染多遍模糊着色器。我想要实现的是制作一个菜单屏幕,在背景上渲染LevelScreen,并在其上应用另一种模糊效果 这是伪代码 protected void render(float delta) { // render the scene to the FBO fbo.begin(); levelScreen.render(delta); fbo.end();

我在LevelScreen渲染方法中使用FBO渲染多遍模糊着色器。我想要实现的是制作一个菜单屏幕,在背景上渲染LevelScreen,并在其上应用另一种模糊效果

这是伪代码

    protected void render(float delta) {
        // render the scene to the FBO
        fbo.begin();
        levelScreen.render(delta);
        fbo.end();

        // retrieve texture and flip Y
        Sprite background = new Sprite(fbo.getColorBufferTexture());
        background.flip(false, true);

        // apply the blurX shader and
        // render the sprite
        batch.setShader(blurH);
        batch.begin();
        background.draw(batch);
        batch.end();
    }
问题是
levelScreen.render()
函数已经包含一个
fbo.begin()
fbo.end()
,场景直接在屏幕上渲染


有没有一种方法可以正确处理嵌套的fbo?

您可以手动处理,使用自定义类来处理帧缓冲区(可能有支持),方法包括
startRender(FrameBuffer)
endRender()
这两种方法可以正确管理事情,例如关闭旧的帧缓冲区,然后打开新的帧缓冲区,等等

此外,请尽量避免在渲染方法内创建新对象

Sprite background = new Sprite(fbo.getColorBufferTexture());
如果这是一个字段,那么它应该可以正常工作

编辑:

如果我理解正确,您当前的问题如下:

FrameBuffer fb1 = ..., fb2 = ...;
fb1.begin();
// draw something on fb1
fb2.begin();
// draw something on fb2
fb2.end();
// draw something on fb1 again
fb1.end();
FrameBuffer fb1 = ..., fb2 = ...;
FrameBufferManager manager = ...;

manager.begin(fb1);
// draw something on fb1
manager.begin(fb2);
// draw something on fb2
manager.end();
// draw something on fb1 again
manager.end();
但是不能同时打开多个帧缓冲区,对吗?因此,创建一个基于堆栈的类来为您管理帧缓冲区,一些简单的事情可以做到:

class FrameBufferManager {
    private Stack<FrameBuffer> stack = new Stack<FrameBuffer>();

    public void begin(FrameBuffer buffer) {
        if (!stack.isEmpty()) {
            stack.peek().end();
        }
        stack.push(buffer).begin();
    }

    public void end() {
        stack.pop().end();
        if (!stack.isEmpty()) {
            stack.peek().begin();
        }
    }
}

不过,不管有没有经理,我都没有尝试过,但它应该能解决你的问题。我不确定每次更改帧缓冲区时是否需要重新打开渲染器和批处理(我通常会这样做)。

这是一个过于简单的解决方案,但这可能就是您所需要的:

将LevelScreen分解为不同的方法:

protected void render(float delta){
    update(delta);
    drawFBOs(delta);
    drawMain(delta);
}
并实现上述三种方法中的每一种。然后还创建此方法,MenuScreen可以使用传入的自己的FBO引用调用此方法

protected void renderToFBO(float delta, FrameBuffer target){
    update(delta); //if necessary
    drawFBOs(delta);
    target.begin();
    drawMain(delta);
    target.end();
}

如果需要设置某些参数,您可以向
drawMain
方法构造函数添加一个布尔值,以确定它是直接绘制到屏幕还是绘制到帧缓冲区。

您能否进一步解释一下您在帧缓冲区堆栈背后的想法?我不知道该怎么做。我只是尝试了你的解决方案,效果很好,而且很透明,谢谢你的绝妙建议@卡哈克斯谢谢兄弟,非常好用。它非常干净,我认为解决它将是一个巨大的麻烦。这个解决方案对我来说也很好,但如果您有复杂的渲染策略,从使用帧缓冲区切换到不使用帧缓冲区,请小心(例如,在进入暂停菜单时开始使用)-渲染策略可能会在渲染循环中发生变化,最终会在空堆栈上调用stack.pop()。我已经尝试过此解决方案,效果很好,但它似乎没有kajacx建议的那样可重用。谢谢你的建议,两种解决方案都有效