I'm using glCopyTexSubImage2D to grab the framebuffer into a texture. Later I restore the screen by drawing that texture on a screen-sized quad. The problem is that the colors of the restored screen image look slightly different than the original. If I capture the left half of the screen and draw it on the right side, there is a slight shift in the colors between the two halves:
http://potatoland.com/code/lwjgl/frame2texture/screen_alpha_compare_clearbg_fins.png
Even if I just clear the background to a color, grab the framebuffer and draw it back, I get a color shift:
http://potatoland.com/code/lwjgl/frame2texture/screen_alpha_compare_clearcolor.png
I have no idea what I'm missing here. Does anybody have a working example of this in LWJGL?
I'm running version .92 Display is 1024 x 768 x 32 @60Hz
Here's the meat of the code:
public void init()
{
// prepare to render in 2D
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glPushMatrix();
GL11.glLoadIdentity();
GL11.glOrtho(0,1024,0,768,-1,1);
// Turn textures on, lighting and depth off
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glDisable(GL11.GL_LIGHTING);
GL11.glDisable(GL11.GL_DEPTH_TEST);
// clear the screen
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
// Create fish texture image
GLImage fishImgL = loadImage("images/fish_angelblue_L.gif");
fishTextureHandleL = makeTexturet(fishImgL.pixelBuffer, fishImgL.w, fishImgL.h);
// Create texture to hold screen image (1024x1024)
screenTxtrHandle = makeTexturet(allocBytes(1024*1024*4), 1024, 1024);
}
public static int makeTexturet(ByteBuffer pixels, int w, int h)
{
int textureHandle = allocateTexture();
GL11.glBindTexture(GL11.GL_TEXTURE_2D,textureHandle);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, w, h, 0,
GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, pixels);
return textureHandle;
}
public void render() {
if (mouseIsDown) {
// draw the saved screen image on right half of screen
GL11.glDisable(GL11.GL_BLEND);
drawQuad(screenTxtrHandle, 512,0, 1024,1024); // plain vanilla textured quad
}
else {
// draw some blended images on the left side of screen
GL11.glClearColor(.1f, .1f, .2f, 1f);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glColor4f(1f, 1f, 1f, .5f);
GLApp.drawImageQuad(fishTextureHandleL, -620, -260, 1200f, 1000f);
GLApp.drawImageQuad(fishTextureHandleL, -520, -160, 1200f, 1000f);
// copy the left half screen to a texture
GL11.glDisable(GL11.GL_BLEND);
GL11.glColor4f(1,1,1,1);
GL11.glReadBuffer(GL11.GL_BACK);
GL11.glBindTexture(GL11.GL_TEXTURE_2D,screenTxtrHandle);
GL11.glCopyTexSubImage2D(GL11.GL_TEXTURE_2D, 0, 0,0, 0,0,512,768);
}
}
full code is at: http://potatoland.com/code/lwjgl/frame2texture/GLApp_FrameSaveTest.java
thanks
Not a LWJGL thing, it's an OpenGL thing. What's going on there is colour quantization. I expect your drivers are reading a 32 bit framebuffer and stuffing it into a 16bit texture. You can try being more explicit about the texture format in your initial call to glTexImage2 eg GL_RGBA8
Cas :)
Thanks Cas,
I wasn't sure whether it's OpenGL or LWJGL, figured I'd start here first.
I'll check the texture format. Thanks for the tip.
mark