I write a game for android using libgdx. If the user opens the pause menu I take a screenshot of the current game, blur it and use it as background for the options menu. This works fine but the code for getting the screenshot is very slow. It takes about 0.8 seconds on average using the code below...
Is there another way to take a screenshot in libgdx which is much faster? If not, when the user opens the options menu I could try to just keep rendering the game, pause the game logic and blur the screen and draw the options on top.. If this is the only fast way, how could one blur the screen? I found this link but I didn't get it to work. If it is possible I prefer the solution with the screenshot because it is much easier...
Code to get the screenshot (from official wiki):
public static Pixmap getScreenshot(){
long start = TimeUtils.millis();
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);
long time = TimeUtils.millis()-start;
Gdx.app.log("INFO", "Time for screenshot in sec.: " + time); // about 0.8 seconds
return pixmap;
}
I use the resulting Pixmap to draw my texture.
EDIT:
My code now with the answer of Deniz Yılmaz for getting the screenshot fast:
public Texture getScreenshot(){
Texture texture = new Texture(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), Pixmap.Format.RGB888);
Gdx.gl.glEnable(GL20.GL_TEXTURE_2D);
Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0);
texture.bind();
Gdx.gl.glCopyTexImage2D(GL20.GL_TEXTURE_2D, 0, GL20.GL_RGB, 0, 0,Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), 0);
Gdx.gl.glDisable(GL20.GL_TEXTURE_2D);
return texture;
}
Actually taking screenshot is not slow. Slow part is data transfer between GPU and CPU so any other way to get pixels wont be faster so much.
But also there are openGl codes helping us right here. You can use opengl codes via Gdx.gl class.
void glCopyTexImage2D(
GLenum target, //Target Opengl Texture
GLint level, //Mipmap level
GLenum internalformat, //Color format
GLint x,
GLint y,
GLsizei width,
GLsizei height,
GLint border);
This function copy pixels into a 2D texture image but not bringing them to CPU. You just belong a FBO at GPU. In libgdx first you must bind texture to openGl's texture with a method. This texture can be empty screen sized texture or you can use old texture you wont use again.
Texture.bind();
or
Gdx.gl.glBindTexture(Opengltexture, texture.getTextureObjectHandle());
For bounding and taking screen
Here is what code look like :
Gdx.gl.glEnable(GL20.GL_TEXTURE_2D);
Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0);
texture.bind();
Gdx.gl.glCopyTexImage2D(GL20.GL_TEXTURE_2D, 0, GL20.GL_RGBA,0, 0,width , height, 0);
Gdx.gl.glDisable(GL20.GL_TEXTURE_2D);
Be aware binding is only active in 1 and 5. My fault was here because i tried to bind texture in create method and had got black screen.
BE AWARE!!!
< uses-feature android:glEsVersion="0x00020000" android:required="true" >
RGBA format color space doesnt supported. So make sure you are using Format.RGB for both opengl function and texture creation.
Result texture will be flipped vertically because of openGl matrix system. So you have to fix it manually.
I also suggest you to look at fragments and shaders. It seems like hard but actually enjoyable.