LibGDX - 绘制到 FrameBuffer 不起作用

Posted

技术标签:

【中文标题】LibGDX - 绘制到 FrameBuffer 不起作用【英文标题】:LibGDX - Drawing to a FrameBuffer does not work 【发布时间】:2014-06-02 21:28:04 【问题描述】:

所以我正在尝试制作自定义按钮,为此我需要组合按钮背景的不同部分。为此,我认为使用 FrameBuffer 会起作用,但是它没有给出可行的结果。因此,我尝试通过编写一个简单的测试方法来测试我的 FrameBuffer 绘制方法,该方法返回在每次 render() 调用时绘制到显示器的纹理。这个方法放在这里(注意是测试方法,所以可能优化的有点差):

    private Texture test()

    BitmapFont f = ReverseBlade.fontTitle;
    f.setColor(Color.LIGHT_GRAY);

    FrameBuffer fbo = new FrameBuffer(Format.RGBA8888, (int)f.getBounds("Hi").width, (int)f.getBounds("Hi").height, false);
    Batch b = ReverseBlade.batch;
    OrthographicCamera c = new OrthographicCamera(fbo.getWidth(), fbo.getHeight());

    c.setToOrtho(false);
    c.update();
    b.setProjectionMatrix(c.combined);

    fbo.begin();
    b.begin();

    f.draw(b, "Hi", 0, 0);

    b.end();
    fbo.end();

    Texture t = fbo.getColorBufferTexture();

    fbo.dispose();

    b.setProjectionMatrix(ReverseBlade.camera.combined);

    return t;

但是,没有显示任何内容。屏幕很暗……我试过不带相机和其他多种我不记得的变体。我做错了什么?

半解 我最终要做的是为 FrameBuffer 创建一个新的 Matrix4 对象,如下所示:

Matrix4 m = new Matrix4();
m.setToOrtho2D(0, 0, fbo.getWidth(), fbo.getHeight());
batch.setProjectionMatrix(m);

但是,这会使绘制的所有内容都颠倒过来,如下所示:

【问题讨论】:

test() 纹理是在哪里绘制的? @noone 给显示,在类的draw(Batch b, float parentAlpha)方法中;这是一个演员。 @noone 我更新了我的问题,如果你想检查一下:3 【参考方案1】:

我认为fbo.dispose() 电话的破坏程度超出了您的预期。

查看the source 并注意它在哪里破坏了colorTexture,这是getColorBufferTexture() 的结果。

我认为这可能被认为是 Libgdx 中的一个错误。颜色纹理通常应该具有与 FBO 完全不同的生命周期,因此清理纹理似乎有点过于激进。然而,试图找出清理纹理的情况可能很复杂......

【讨论】:

这可能是原因。但我不确定它是否可以被认为是一个错误或过于激进的资源清理。纹理和 FBO 应该具有相同的生命周期恕我直言。我不确定这里的 OpenGL 内部结构,但是在处理 FBO 时,是否仍然可以访问它正在渲染的“纹理”? 所以我注释掉了 dispose 调用并将文本的绘制 Y 坐标设置为 fbo.getHeight() 并且我设法看到一小片明亮的像素(Y 为 0 我什么也看不到)。【参考方案2】:

因此,按照我使用半解决方案添加的内容,我所要做的就是使用来自 FBo 的纹理创建一个新的 Sprite 对象并调用 Flip(false, true)!

【讨论】:

【参考方案3】:

可能这是 dispose() 帧缓冲区并保持纹理活动的解决方法。我执行以下操作:

public class TextureSaveFBO extends FrameBuffer 
    static final Texture DUMMY = new Texture(1, 1, Format.RGB565) 
        public void dispose() 
        ;
    ;

    public TextureSaveFBO(Format format, int width, int height,
            boolean hasDepth) 
        super(format, width, height, hasDepth);
    

    @Override
    public void dispose() 
        // prevents the real texture of dispose()
        Texture t = colorTexture;
        colorTexture = DUMMY;
        super.dispose();
        colorTexture = t;
    

【讨论】:

没想到我会需要这个,但是在重新评估了我的项目将如何组织之后,我意识到我肯定会!谢谢你让我知道:)【参考方案4】:

只是一个精确度:

OrthographicCamera c = new OrthographicCamera(fbo.getWidth(), fbo.getHeight());
c.setToOrtho(false);

除非您知道自己在做什么,否则这可能有害:c.setOrtho(false) 执行以下操作:

使用适合屏幕分辨率的视口将此相机设置为正交投影,以 (Gdx.graphics.getWidth()/2, Gdx.graphics.getHeight()/2) 为中心,y 轴朝上或下来。

因此,即使您在 OrthographicCamera 的构造函数中指定您希望视口具有帧缓冲区大小,您也将通过以下调用覆盖屏幕大小并以屏幕中心为中心的视口来覆盖它。

你应该这样做:

camera.setToOrtho(false, fbo.getWidth(), fbo.getHeight());

【讨论】:

哇,我什至没有注意到这一点。感谢您引起我的注意 :) 我已经放弃使用 FrameBufferObjects 转而使用更方便的方法,但是作为将来的参考真的很高兴!【参考方案5】:

Issue 自 LibGDX 1.6.5 起已解决。

现在可以重写 disposeColorBuffer 方法以不处理渲染的纹理。

【讨论】:

是的,我在 github 补丁说明中看到了。很高兴这已得到修复。

以上是关于LibGDX - 绘制到 FrameBuffer 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

如何在 libgdx 中正确设置 FrameBuffer 的宽度和高度?

libGDX:FrameBuffer 大小限制 == 最大纹理大小?

LibGDX FrameBuffer 混合

LibGDX - 无法从 FrameBuffer 获取纹理

如何正确使用 LIBGDX FrameBuffer

libgdx 中的 FrameBuffer 大小