如何使用LibGDX生成透明的PNG图像?

时间:2018-07-26 15:54:50

标签: java libgdx png lwjgl

我想将自己的LibGDX游戏的一个实体渲染为PNG。因此,我做了一个小的工具,它是一个LibGDX应用程序,用于显示该实体,并在F5上截屏。该应用程序的目标只是生成PNG。

camera.update();

Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL_COLOR_BUFFER_BIT);

batch.setProjectionMatrix(camera.combined);
batch.begin();

animation.update(Gdx.graphics.getDeltaTime() * 1000);
animation.draw(batch);

batch.end();

if(exporting)
    // export...

从该wiki page中我了解了如何制作屏幕截图,并且通过删除了for循环,我能够获得一个屏幕截图,该屏幕截图无法用黑色像素代替透明像素。

byte[] pixels = ScreenUtils.getFrameBufferPixels(0, 0, Gdx.graphics.getBackBufferWidth(), Gdx.graphics.getBackBufferHeight(), true);

Pixmap pixmap = new Pixmap(Gdx.graphics.getBackBufferWidth(), Gdx.graphics.getBackBufferHeight(), Pixmap.Format.RGBA8888);
BufferUtils.copy(pixels, 0, pixmap.getPixels(), pixels.length);
PixmapIO.writePNG(Gdx.files.external("mypixmap.png"), pixmap);
pixmap.dispose();

它适用于实体的边缘,但不适用于内部的多个部分。

边缘:(完美)

Edges

内部:(不应透明)

Inside

所以我开始玩混合游戏来解决这个问题。 使用

batch.enableBlending();
batch.setBlendFunction(
            exporting ? GL20.GL_ONE : GL20.GL_SRC_ALPHA, // exporting is set to true on the frame where the screenshot is taken
            GL20.GL_ONE_MINUS_SRC_ALPHA);

这对它有所改进:

Inside working

但是对于像眼镜这样的图像来说,它们应该是透明的,所以它是不透明的:

Opaque glasses

代替:

Transparent glasses

我应该怎么做才能解决这个问题?我想要的是非常标准的,透明的背景,上面有半透明的图像。我希望它的行为就像普通的图像软件那样具有分层(如GIMP)。

1 个答案:

答案 0 :(得分:1)

您的问题是因为书写的颜色和alpha均由相同的功能SRC_ALPHA和ONE_MINUS_SRC_ALPHA调制。

您需要使用glBlendFuncSeparate实现此目的。就您而言:

batch.begin();

// first disable batch blending changes (see javadoc)
batch.setBlendFunction(-1, -1);

// then use special blending.
Gdx.gl.glBlendFuncSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA,GL20.GL_SRC_ALPHA, GL20.GL_DST_ALPHA);

... your drawings ...

batch.end();

通过这种方式,颜色通道仍然像往常一样进行混合,但是添加了alpha通道(源和目标)。

请注意,对于libgdx 1.9.7+,不再需要批量混合技巧,而可能是:

batch.begin();

batch.setBlendFunctionSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA,GL20.GL_SRC_ALPHA, GL20.GL_DST_ALPHA);

... your drawings ...

batch.end();