Frame Buffer Object doesn't render properly

I’m trying to shoehorn JOGL into doing some 2D compositing for me. The clear operation works correctly; unfortunately, whenever I render to my frame buffer object after that, instead of an overlay operation occuring it seems a multiply is done instead. I’ve fiddled with lots of parameters, but can’t stop this.

The depth test should always pass, so there really isn’t a need for a depth buffer, but the problem happens with or without it. The blend function should be glBlend(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

What’s the right way to draw new images over top of whatever’s in my back buffer?


public class FBOPanel extends javax.swing.JPanel implements GLEventListener
{
    private GLCanvas canvas;
    
    int frameBufferId;
    int depthId;
    int texId;
    
    int destWidth = 512;
    int destHeight = 256;
    
    /** Creates new form TexRectanglePanel */
    public FBOPanel()
    {
        initComponents();
        
    }
    
    public void addNotify()
    {
        super.addNotify();
        canvas = new GLCanvas(new GLCapabilities());
        canvas.addGLEventListener(this);
        
        add(canvas, BorderLayout.CENTER);
    }
    

    public void init(GLAutoDrawable gLAutoDrawable)
    {
        GL gl = gLAutoDrawable.getGL();
        
        //-----------------------------------------------
        IntBuffer ibuf = BufferUtil.newIntBuffer(1);
        
        gl.glGenFramebuffersEXT(1, ibuf);
        frameBufferId = ibuf.get(0);
        ibuf.rewind();
        gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, frameBufferId);
        
        gl.glGenRenderbuffersEXT(1, ibuf);
        depthId = ibuf.get(0);
        ibuf.rewind();
        
        gl.glGenTextures(1, ibuf);
        texId = ibuf.get(0);
        ibuf.rewind();
        

        gl.glBindRenderbufferEXT(GL.GL_RENDERBUFFER_EXT, depthId);
        gl.glRenderbufferStorageEXT(GL.GL_RENDERBUFFER_EXT, GL.GL_DEPTH_COMPONENT,
                destWidth, destHeight);
        gl.glFramebufferRenderbufferEXT(GL.GL_FRAMEBUFFER_EXT, 
                GL.GL_DEPTH_ATTACHMENT_EXT, GL.GL_RENDERBUFFER_EXT, depthId);
        
        
        ByteBuffer imgData = BufferUtil.newByteBuffer(destWidth * destHeight * 4);
        
        gl.glEnable(GL.GL_TEXTURE_RECTANGLE_ARB);
        gl.glBindTexture(GL.GL_TEXTURE_RECTANGLE_ARB, texId);
        //Create empty texture
        gl.glTexImage2D(GL.GL_TEXTURE_RECTANGLE_ARB, 0, GL.GL_RGBA, 
                destWidth, destHeight, 
                0, GL.GL_RGBA, 
                GL.GL_UNSIGNED_BYTE, imgData);
        
        //Attach texture back buffer
        gl.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT, 
                GL.GL_COLOR_ATTACHMENT0_EXT, GL.GL_TEXTURE_RECTANGLE_ARB, texId, 0);
        
//        gl.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE);
        
        int status = gl.glCheckFramebufferStatusEXT (GL.GL_FRAMEBUFFER_EXT);
        switch (status)
        {
        case GL.GL_FRAMEBUFFER_COMPLETE_EXT:
                System.out.println("FrameBuffer Created");
            break;
        case GL.GL_FRAMEBUFFER_UNSUPPORTED_EXT:
            System.out.println("FBO configuration unsupported");
            break;
        default:
            System.out.println( "FBO programmer error" );
            break;
        }        
    }

    public void display(GLAutoDrawable gLAutoDrawable)
    {
        GL gl = gLAutoDrawable.getGL();
        
        gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, frameBufferId);
        gl.glPushAttrib(GL.GL_ALL_ATTRIB_BITS);
        
        gl.glViewport(0, 0, destWidth, destHeight);
        
        gl.glEnable(GL.GL_BLEND);
        gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);

        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);


        gl.glMatrixMode(GL.GL_PROJECTION);
        {
            gl.glLoadIdentity();
            gl.glFrustum(-1, 1, -1, 1, 1.5, 20);
        }
        gl.glMatrixMode(GL.GL_MODELVIEW);

        gl.glColor3f(1, 0, 1);
        gl.glLoadIdentity();
        
        GLU glu = new GLU();
        glu.gluLookAt(0, 0, 5, 0, 0, 0, 0, 1, 0);
        gl.glScalef(1.0f, 2.0f, 1.0f);
        GLUT glut = new GLUT();
        glut.glutWireCube(1);
         
        gl.glFlush();

        gl.glPopAttrib();
        gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 0);
        
        //Save image
        ByteBuffer imgData = BufferUtil.newByteBuffer(destWidth * destHeight * 4);
        gl.glGetTexImage(GL.GL_TEXTURE_RECTANGLE_ARB, 
                0, //Mipmap level
                GL.GL_RGBA, GL.GL_UNSIGNED_BYTE,
                imgData);
        
        BufferedImage img = new BufferedImage(destWidth, destHeight, BufferedImage.TYPE_INT_ARGB);
        imgData.rewind();
        WritableRaster raster = img.getRaster();
        for (int j = raster.getHeight() - 1; j >= 0; j--)
        {
            for (int i = 0; i < raster.getWidth(); i++)
            {
                raster.setSample(i, j, 0, imgData.get());
                raster.setSample(i, j, 1, imgData.get());
                raster.setSample(i, j, 2, imgData.get());
                raster.setSample(i, j, 3, imgData.get());
            }
        }

        try
        {
            ImageIO.write(img, "png", new File("fboImage.png"));
        } 
        catch (IOException ex)
        {
            ex.printStackTrace();
        }
    }

    public void reshape(GLAutoDrawable gLAutoDrawable, int i, int i0, int i1, int i2)
    {
    }

    public void displayChanged(GLAutoDrawable gLAutoDrawable, boolean b, boolean b0)
    {
    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    private void initComponents()
    {

        setLayout(new java.awt.BorderLayout());

    }// </editor-fold>                        
    
    
}


Looks like I shouldn’t have made a call to glEnable(GL.GL_RECTANGLE_ARB). I was texturing my object with the background buffer.