如何使用 LibGDX 生成透明的 PNG 图片?
How to generate a transparent PNG image with LibGDX?
我的 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();
它适用于实体的边缘,但不适用于内部的多个部分。
边缘:(完美)
内部:(不应该是透明的)
所以我开始尝试混合来解决这个问题。
随着
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);
这改进了一点:
但是眼镜之类的图像本应是透明的,但它却是不透明的:
而不是:
知道我应该如何解决这个问题吗?我想要的是非常标准的,一个透明的背景,上面有半透明的图像。我希望它的行为就像带有图层的常规图像软件(如 GIMP)一样。
您的问题是因为书写颜色和 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_ONE, GL20.GL_ONE);
... your drawings ...
batch.end();
这样,颜色通道仍然像往常一样混合,但添加了 alpha 通道(源和目标)。
请注意,在 libgdx 1.9.7+ 中,不再需要批量混合 hack,可以是:
batch.begin();
batch.setBlendFunctionSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA,GL20.GL_ONE, GL20.GL_ONE);
... your drawings ...
batch.end();
虽然在某些情况下有一些限制,请查看 my GIST 了解更多信息。
我的 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();
它适用于实体的边缘,但不适用于内部的多个部分。
边缘:(完美)
内部:(不应该是透明的)
所以我开始尝试混合来解决这个问题。 随着
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);
这改进了一点:
但是眼镜之类的图像本应是透明的,但它却是不透明的:
而不是:
知道我应该如何解决这个问题吗?我想要的是非常标准的,一个透明的背景,上面有半透明的图像。我希望它的行为就像带有图层的常规图像软件(如 GIMP)一样。
您的问题是因为书写颜色和 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_ONE, GL20.GL_ONE);
... your drawings ...
batch.end();
这样,颜色通道仍然像往常一样混合,但添加了 alpha 通道(源和目标)。
请注意,在 libgdx 1.9.7+ 中,不再需要批量混合 hack,可以是:
batch.begin();
batch.setBlendFunctionSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA,GL20.GL_ONE, GL20.GL_ONE);
... your drawings ...
batch.end();
虽然在某些情况下有一些限制,请查看 my GIST 了解更多信息。