【问题标题】:Libgdx - different sizes when framebuffer's texture is rendered to screenLibgdx - 将帧缓冲区的纹理渲染到屏幕时的不同大小
【发布时间】:2024-01-20 03:30:01
【问题描述】:

由于我的设计,我想摆脱 NinePatch 对象,但我使用它使用帧缓冲区以所需大小初始化纹理,然后将该纹理应用到我的自定义对象

我是 LibGDX 和 GL 的新手。

问题是当我绘制 FBO 纹理来筛选图像时,图像太小了,不知道为什么

我从这里抓取所有这些的骨架:https://*.com/a/7632680/401529

我的 RenderToTexture 类是:

public class RenderToTexture {
private float fbScaler = 1f;
private boolean fbEnabled = true;
private FrameBuffer fb = null;
private TextureRegion fbReg = null;


[... more constructors ... ]

/**
 *
 * @param scale
 */
public RenderToTexture(int width, int height, float scale, boolean hasDepth) {
    if(width == -1){
        width = (int) (Gdx.graphics.getDisplayMode().width * scale);
    }
    if(height == -1){
        height = (int) (Gdx.graphics.getDisplayMode().height * scale);
    }

    fb = new FrameBuffer(
            Pixmap.Format.RGBA8888,
            (int)(width * fbScaler),
            (int)(height * fbScaler),
            hasDepth
    );

    fbReg = new TextureRegion(fb.getColorBufferTexture());
    fbReg.flip(false,false);
}

public void begin(){
    if(fbEnabled) {
        fb.begin();
        Gdx.gl.glClearColor(0, 0,0,0);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    }
}
public TextureRegion end(){
    if(fb != null)
    {
        fb.end();
        return fbReg;
        // batch.draw(fboRegion, 0, 0);
    }
    return null;
}

}

还有我的 util 类:

public class ImageUtils {
public static TextureRegion ninePatchToTextureRegion(NinePatch patch, int width, int height){
    return ninePatchToTextureRegion(new NinePatchDrawable(patch), width, height);
}

public static TextureRegion ninePatchToTextureRegion(NinePatchDrawable patch, int width, int height){
    RenderToTexture r2t = new RenderToTexture(width, height, 1, false);
    SpriteBatch sb = new SpriteBatch();
    r2t.begin();
    sb.begin();
    patch.draw(sb, 0, 0, width, height);
    sb.end();
    sb.dispose();

    return r2t.end();
}

}

然后我在创建精灵时调用这个 util 类:

NinePatchDrawable ninepatchtest = new NinePatchDrawable(
                new NinePatch(new Texture(Gdx.files.internal("img/ui/btn-retro-blue.png")), 5, 5, 5, 5)
        );
TextureRegion result = ImageUtils.ninePatchToTextureRegion(ninepatchtest, 200, 100);
        sprite = new Sprite(result);

当前结果是(左)和大小模拟期望结果(右)

编辑:相机尺寸是显示模式尺寸,粘在屏幕上,没有缩放,没有移动。

编辑:修正了 @Tenfour04 建议的丢失处置

如果这种方式不是最好的方式,我愿意接受新的选择

【问题讨论】:

    标签: java libgdx lwjgl framebuffer


    【解决方案1】:

    好吧,我找到了解决问题的“一半”:

    正如我在此示例中看到的 LibGDX - Drawing to a FrameBuffer does not work 我错过了 SpriteBatch 对象的 setProjectionMatrix,所以现在渲染到纹理类 begin() 方法是:

    public SpriteBatch begin(){
        SpriteBatch batch = null;
    
        if(fbEnabled) {
            fb.begin();
            Gdx.gl.glClearColor(0, 0,0,0);
            Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
            Matrix4 m = new Matrix4();
            m.setToOrtho2D(0, 0, fb.getWidth(), fb.getHeight());
    
            batch = new SpriteBatch();
            batch.setProjectionMatrix(m);
        }
    
        return batch;
    }
    

    现在 renderToTexture begin() 返回 spritebatch,所以:

    public static TextureRegion ninePatchToTextureRegion(NinePatchDrawable patch, int width, int height){
        RenderToTexture r2t = new RenderToTexture(width, height, 1, false);
        SpriteBatch sb = r2t.begin();
        sb.begin();
        patch.draw(sb, 0, 0, width, height);
        sb.end();
        sb.dispose();
        return r2t.end();
    }
    

    这解决了从FBO绘制纹理的大小,但是ninepatch在framebuffer之外绘制ok,并用framebuffer拉伸...

    【讨论】:

    • 试试看这个纹理缩放,因为你说你是 OpenGL 的新手:open.gl/textures
    • 您正在泄漏您的 SpriteBatch。 SpriteBatches 必须被释放。而且它们是需要大量时间来实例化的大对象,因此您应该在游戏的整个生命周期内重用一个实例。
    • @NickClark2016 我很好奇为什么 spritebatch 在 fbo 内绘制拉伸的 Ninepatch,并且在没有 fbo 的情况下渲染得很好
    • @Tenfour04 我修复了丢失的 dispose,在类外重用主批处理,无论如何在游戏循环外初始化时使用了 render2texture