LWJGL Forum

Programming => Lightweight Java Gaming Library => Topic started by: manji on August 26, 2009, 21:12:15

Title: white/inverted textures when using glCopyTexImage2D [SOLVED]
Post by: manji on August 26, 2009, 21:12:15
I am trying to copy my screen(everything rendered in the display, or part of it) to a texture. I use this function:
public void screenToTexture(){
   GL11.glViewport(0, 0, 512, 512);    
   GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID);
   GL11.glCopyTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, 0, 0, 512, 512, 0);
   GL11.glViewport(0, 0, 1024, 768);
}

When later I bind this texture and map it on a square, all I get is a white texture. I know I am doing something wrong, could someone plz guide me?
Title: Re: white textures when using glCopyTexImage2D
Post by: bobjob on August 27, 2009, 01:02:26
you could always try testing glReadPixels instead. I have had problems with glCopyTestImage2D in the past
Title: Re: white textures when using glCopyTexImage2D
Post by: manji on August 27, 2009, 07:19:21
Thnx, I'll try that.
Title: Re: white textures when using glCopyTexImage2D
Post by: broumbroum on August 27, 2009, 12:23:51
Quote from: manji on August 26, 2009, 21:12:15
(...)
   GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID);
   GL11.glCopyTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, 0, 0, 512, 512, 0);

When later I bind this texture and map it on a square, all I get is a white texture. I know I am doing something wrong, could someone plz guide me?
You may have to invert textureID with the copyTexImage2D name, which is 0 i guess. Is that the screen you want to copy ? screen is 0, then must be bound instead.
Title: Re: white textures when using glCopyTexImage2D
Post by: manji on August 27, 2009, 13:07:37
@broumbroum I am sorry, but I didn't get what you suggest. If you say that I should bind the right texture, I already do that. Before rendering a cube, I am sure I bind the texture that this textureID refers to. textureID is defined by:
public int createTextureID(){
  IntBuffer tmp = createIntBuffer(1);
  GL11.glGenTextures(tmp);
  return tmp.get(0);
}

and before drawing the cube, I do:
GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID);

@bobjob I tried the function I saw here http://lwjgl.org/forum/index.php/topic,867.0.html (http://lwjgl.org/forum/index.php/topic,867.0.html) that uses glReadPixels to copy the screen to BufferedImage and then I copy it to a texture. I did saw an inverted texture of my screen once, so there is a hope here. I will check it more thoroughly later and will post the results.
Title: Re: white textures when using glCopyTexImage2D
Post by: broumbroum on August 27, 2009, 14:34:41
I might explain further : What you want to do is copy the screen and render with a texture. 
Quote from: glcopyteximage2d-docglCopyTexImage2D defines a two-dimensional texture image
     with pixels from the current GL_READ_BUFFER.
that is you have to generate a buffer name, bind it : glbindbuffer to gl_pixel_pack_buffer and then read your screen frame buffer :
Quote from: glreadpixelsIf a non-zero named buffer object is bound to the GL_PIXEL_PACK_BUFFER target (see glBindBuffer) while a block of pixels is requested, data is treated as a byte offset into the buffer object's data store rather than a pointer to client memory.
then obviously the pixel data will stay in the newly created buffer for which it can be requested the copy to a texture.
genbuffer > bindbuffer > readpixels > copyteximage2d > bindtexture > render the cube :P
Title: Re: white textures when using glCopyTexImage2D
Post by: manji on August 27, 2009, 15:51:00
@broumbroum I really thank very much for your time, but I am not so sure how to implement this right now ???. So, for the time being I'll stick to the following.

I have gathered some functions I have found here and there, and the best I can do is copy the screen to a texture, but inverted. The procedure is the following:
At first, I take a screenshot in a BufferedImage object:
public BufferedImage screenShot(int width, int height){
    BufferedImage screenshot = null;
     // allocate space for RBG pixels
     ByteBuffer fb = GLApp.allocBytes(width * height * 3);
     int[] pixels = new int[width * height];
     int bindex;
     // grab a copy of the current frame contents as RGB
     GL11.glReadPixels(0, 0, width, height, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, fb);
     // convert RGB data in ByteBuffer to integer array
     for (int i=0; i < pixels.length; i++) {
         bindex = i * 3;
         pixels[i] =
             ((fb.get(bindex) << 16))  +
             ((fb.get(bindex+1) << 8))  +
             ((fb.get(bindex+2) << 0));
     }
     // Create a BufferedImage with the RGB pixels then save as PNG
     try {
         screenshot = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
         screenshot.setRGB(0, 0, width, height, pixels, 0, width);
         //javax.imageio.ImageIO.write(screenshot, "png", new File("screenshot_test.png"));
     }
     catch (Exception e) {
         System.out.println("ScreenShot() exception: " +e);
     }
     return screenshot;
}

Then I convert this byteBuffer to a Texture(from spaceinvaders source) object:
public Texture getTexture(BufferedImage image,
                          int target,
                          int dstPixelFormat,
                          int minFilter,
                          int magFilter) throws IOException
{
    int srcPixelFormat = 0;

    // create the texture ID for this texture
    int textureID = createTextureID();
    Texture texture = new Texture(target,textureID);

    // bind this texture
    GL11.glBindTexture(target, textureID);

    BufferedImage bufferedImage = image;
    texture.setWidth(bufferedImage.getWidth());
    texture.setHeight(bufferedImage.getHeight());

    if (bufferedImage.getColorModel().hasAlpha()) {
        srcPixelFormat = GL11.GL_RGBA;
    } else {
        srcPixelFormat = GL11.GL_RGB;
    }

    // convert that image into a byte buffer of texture data
    ByteBuffer textureBuffer = convertImageData(bufferedImage,texture);

    if (target == GL11.GL_TEXTURE_2D)
    {
        GL11.glTexParameteri(target, GL11.GL_TEXTURE_MIN_FILTER, minFilter);
        GL11.glTexParameteri(target, GL11.GL_TEXTURE_MAG_FILTER, magFilter);

    }

    // produce a texture from the byte buffer
    GL11.glTexImage2D(target,
                  0,
                  dstPixelFormat,
                  get2Fold(bufferedImage.getWidth()),
                  get2Fold(bufferedImage.getHeight()),
                  0,
                  srcPixelFormat,
                  GL11.GL_UNSIGNED_BYTE,
                  textureBuffer );

    return texture;
}

And finally I bind the texture before rendering. The weird thing is that the texture is rendered fire, but inverted. Any clue?
Title: Re: white/inverted textures when using glCopyTexImage2D
Post by: bobjob on August 27, 2009, 17:08:38
the java co-ordinate system is different to the OpenGL one.

so it may be that you are copying pixels from the bottom left in opengl
then drawing them from the top-right in bufferedImage object.
Title: Re: white textures when using glCopyTexImage2D
Post by: broumbroum on August 27, 2009, 19:37:47
Quote from: manji on August 27, 2009, 15:51:00
@broumbroum I really thank very much for your time, but I am not so sure how to implement this right now ???. So, for the time being I'll stick to the following.
And finally I bind the texture before rendering. The weird thing is that the texture is rendered fire, but inverted. Any clue?
It's alright, yet I think openGL has some issues where it is hard to find your way out because opengl is not as handy as java. 8)
Quote
so it may be that you are copying pixels from the bottom left in opengl
then drawing them from the top-right in bufferedImage object.
then it might be the case to flip the buffer returned by converttobufferedimage.
Title: Re: white/inverted textures when using glCopyTexImage2D
Post by: manji on September 01, 2009, 10:21:45
I guess you mean flipping the BufferedImage object. I did that, using things from here, http://www.exampledepot.com/egs/java.awt.image/Flip.html (http://www.exampledepot.com/egs/java.awt.image/Flip.html) and here http://www.java2s.com/Code/Java/Advanced-Graphics/FlippingaBufferedImage.htm (http://www.java2s.com/Code/Java/Advanced-Graphics/FlippingaBufferedImage.htm), and also using GLImage class http://potatoland.org/code/gl/javadoc/glapp/GLImage.html#flipY(java.awt.image.BufferedImage (http://potatoland.org/code/gl/javadoc/glapp/GLImage.html#flipY(java.awt.image.BufferedImage) . The same inverted image appears. If I make any progress, I will post again.

Update: No wait, my mistake, this thing actually works! :
// Flip the image vertically
AffineTransform tx = AffineTransform.getScaleInstance(1, -1);
tx.translate(0, -img.getHeight(null));
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
img = op.filter(img, null);

Thank you very much both of you! There is still an anomaly in the lower side of the texture(smth like clamping), but I hope I will fix it.