Login  Register

Re: FBO with GLCanvas

Posted by Bob on Nov 27, 2019; 11:57am
URL: https://forum.jogamp.org/FBO-with-GLCanvas-tp4040147p4040148.html

Here is the full code I used to make tests:

public class TestsCanvasFBO implements GLEventListener
{
    private static int fboId = -1;

    private static boolean doScreenshot = false;

    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(
            () ->
            {
                GLProfile glp = GLProfile.getDefault();
                GLCapabilities caps = new GLCapabilities(glp);
                GLCanvas canvas = new GLCanvas(caps);
                canvas.addGLEventListener(new TestsCanvasFBO());

                Button screenshotButton = new Button("Screenshot");
                screenshotButton.addActionListener(e ->
                                                   {
                                                       doScreenshot = true;
                                                       canvas.display();
                                                   });

                Frame frame = new Frame("FBO Test");
                frame.setSize(1000, 1000);
                frame.add(canvas, BorderLayout.CENTER);
                frame.add(screenshotButton, BorderLayout.PAGE_END);
                frame.setVisible(true);
            });
    }

    @Override
    public void init(GLAutoDrawable drawable)
    {
        //        drawable.setGL(new DebugGL2(drawable.getGL().getGL2()));
        drawable.getGL().glClearColor(0, 0, 0, 1);
        initialiseFBO(drawable.getGL(), drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
    }

    private static void initialiseFBO(GL gl, int width, int height)
    {
        // Framebuffer creation
        // ----------------------
        int[] ids = new int[1];
        gl.glGenFramebuffers(1, ids, 0);
        fboId = ids[0];

        gl.glGenRenderbuffers(1, ids, 0);
        int rbId = ids[0];

        gl.glBindFramebuffer(GL_FRAMEBUFFER, fboId);
        gl.glBindRenderbuffer(GL_RENDERBUFFER, rbId);
        gl.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);

        // Texture creation
        // ------------------
        gl.glGenTextures(1, ids, 0);
        int tId = ids[0];
        gl.glBindTexture(GL_TEXTURE_2D, tId);
        gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, null);

        // Attach texture and render buffer to FBO
        // ----------------------------------------
        gl.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tId, 0);
        gl.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbId);
        gl.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbId);

        gl.glBindTexture(GL_TEXTURE_2D, 0);
        gl.glBindFramebuffer(GL_FRAMEBUFFER, 0);
    }

    @Override
    public void display(GLAutoDrawable drawable)
    {
        GL2 gl = drawable.getGL().getGL2();

        if (doScreenshot)
        {
            gl.glBindFramebuffer(GL_FRAMEBUFFER, fboId);
            gl.glClearColor(1, 1, 1, 1);
        }
        else
        {
            gl.glClearColor(0, 0, 0, 1);
        }

        gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        gl.glColor3f(1, 0, 0);
        gl.glBegin(GL2.GL_POLYGON);
        {
            gl.glVertex2f(0.5f, 0.5f);
            gl.glVertex2f(-0.5f, 0.5f);
            gl.glVertex2f(-0.5f, -0.5f);
            gl.glVertex2f(0.5f, -0.5f);
            gl.glVertex2f(0f, 0f);
        }
        gl.glEnd();

        if (doScreenshot)
        {
            gl.glFinish();

            capture(gl);

            gl.glBindFramebuffer(GL_FRAMEBUFFER, 0);
            doScreenshot = false;
        }
    }

    private static void capture(GL gl)
    {
        // Create image
        BufferedImage bi = new AWTGLReadBufferUtil(gl.getGLProfile(), false).readPixelsToBufferedImage(gl, true);
        try
        {
            ImageIO.write(bi, "PNG", new File("./capture.png"));
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    @Override
    public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h)
    {
    }

    @Override
    public void dispose(GLAutoDrawable drawable)
    {
        deleteFBO(drawable);
    }

    private void deleteFBO(GLAutoDrawable drawable)
    {
        GL gl = drawable.getGL();

        // Dispose resources
        int[] ids = new int[1];
        // Texture
        gl.glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, ids, 0);
        gl.glDeleteTextures(1, ids, 0);

        // Render buffer
        gl.glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, ids, 0);
        gl.glBindRenderbuffer(GL_RENDERBUFFER, 0);
        gl.glDeleteRenderbuffers(1, ids, 0);

        // Frame buffer
        gl.glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, ids, 0);
        gl.glBindFramebuffer(GL_FRAMEBUFFER, 0);
        gl.glDeleteFramebuffers(1, ids, 0);
    }
}