Search code examples
openglfbo

Fbo textures get flipped/rotated


I am capturing a couple of images through fbo's. I then reuse these images, adding something to them (using fbo's and shaders). Now, for some reason the images get rotated and I have no idea where it happens.

Below some of the code the bug may be connected with. I can supply more code on request.

I save the images like this:

glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
            int bpp = 4; // Assuming a 32-bit display with a byte each for red, green, blue, and alpha.
            ByteBuffer buffer = BufferUtils.createByteBuffer(SAVE_WIDTH * SAVE_HEIGHT * bpp);
            glReadPixels(0, 0, SAVE_WIDTH, SAVE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, buffer );

            File file = new File("picture" + k + ".png"); // The file to save to.
            String format = "png"; // Example: "PNG" or "JPG"
            BufferedImage image = new BufferedImage(SAVE_WIDTH, SAVE_HEIGHT, BufferedImage.TYPE_INT_ARGB);

            for(int x = 0; x < SAVE_WIDTH; x++)
                for(int y = 0; y < SAVE_HEIGHT; y++)
                {
                        int i = (x + (SAVE_WIDTH * y)) * bpp;
                        int r = buffer.get(i) & 0xFF;
                        int g = buffer.get(i + 1) & 0xFF;
                        int b = buffer.get(i + 2) & 0xFF;
                        int a = buffer.get(i + 3) & 0xFF;
                        image.setRGB(x, SAVE_HEIGHT - (y + 1), (a << 24) | (r << 16) | (g << 8) | b);
                }


            try {
                ImageIO.write(image, format, file);
            } catch (IOException e) { 
                e.printStackTrace(); 
            }

And I load them like this:

  ByteBuffer buf = null;
        File file = new File(filename);

        if (file.exists()) {

            try {
                BufferedImage image = ImageIO.read(file);

                buf = Util.getImageDataFromImage(image);
            } catch (IOException ex) {
                Logger.getLogger(SkyBox.class.getName()).log(Level.SEVERE, null, ex);
            }
        } else {
            int length = SAVE_WIDTH * SAVE_HEIGHT * 4;
            buf = ByteBuffer.allocateDirect(length);
            for (int i = 0; i < length; i++)
                buf.put((byte)0xFF);
            buf.rewind();
        }

        // Create a new texture object in memory and bind it
        glBindTexture(GL_TEXTURE_2D, pictureTextureId);

        // All RGB bytes are aligned to each other and each component is 1 byte
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

        // Upload the texture data and generate mip maps (for scaling)
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SAVE_WIDTH, SAVE_HEIGHT, 0, 
                        GL_RGBA, GL_UNSIGNED_BYTE, buf);    

        // Setup what to do when the texture has to be scaled
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 
                        GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 
                        GL_NEAREST);

getImageDataFromImage()

    WritableRaster wr = bufferedImage.getRaster();
    DataBuffer db = wr.getDataBuffer();
    DataBufferByte dbb = (DataBufferByte) db;
    ByteBuffer byteBuffer = ByteBuffer.allocateDirect(dbb.getData().length);

    byte[] bytes = dbb.getData();

    for(int i=0; i<bytes.length; i+=4) {
        byteBuffer.put(bytes[i+3]);
        byteBuffer.put(bytes[i+2]);
        byteBuffer.put(bytes[i+1]);
        byteBuffer.put(bytes[i]);
    }

    byteBuffer.flip();
    return byteBuffer;

Solution

  • Rotated, or flipped in the vertical? If they're flipped, then that's because OpenGL and image file formats don't neccesarily agree on the origin of the coordinate system. With OpenGL and the usual projection setups the origin is in the lower left. Most image file formats and IO libraries assume the origin in the upper left.