querying textures bound to default draw/read framebuffers

classic Classic list List threaded Threaded
10 messages Options
ac
Reply | Threaded
Open this post in threaded view
|

querying textures bound to default draw/read framebuffers

ac
Hello, I'm testing the new FBO-based offscreen Drawable mechanism. So far, I figured out that the GL id's of the draw and read framebuffers can be retrieved with GLContext.getDefaultDrawFramebuffer() and GLContext.getDefaultReadFramebuffer(). For certain applications, I'd also need to access the name of the texture used as the back color buffer, but I haven't found a way to do so. Any suggestions?

Reply | Threaded
Open this post in threaded view
|

Re: querying textures bound to default draw/read framebuffers

Sven Gothel
Administrator
On 10/20/2012 04:39 AM, ac [via jogamp] wrote:
> Hello, I'm testing the new FBO-based offscreen Drawable mechanism. So far, I
> figured out that the GL id's of the draw and read framebuffers can be
> retrieved with GLContext.getDefaultDrawFramebuffer() and
> GLContext.getDefaultReadFramebuffer(). For certain applications, I'd also need
> to access the name of the texture used as the back color buffer, but I haven't
> found a way to do so. Any suggestions?

Ofc .. looks at the unit tests, it's a GLFBO[Auto]Drawable
what you receive w/ certain factory methods.
This FBO specific drawable allows you to retrieve the FBObject,
which discloses all the details to you.
Details which are inspired by you :)

~Sven



signature.asc (907 bytes) Download Attachment
ac
Reply | Threaded
Open this post in threaded view
|

Re: querying textures bound to default draw/read framebuffers

ac
Hello Sven, thanks for your reply. All this new API to handle the FBOs looks great, but I'm still unsure how to properly integrate with my old code. I've been looking at TestFBOAutoDrawableFactoryNEWT.java, and I think I understand how the unit tests work. Based on that, I added the following code at the end of my JOGL initialization function (where I create the request capabilities, the canvas object, etc):

final GLDrawableFactory factory = GLDrawableFactory.getFactory(profile);
GLOffscreenAutoDrawable.FBO glad = (GLOffscreenAutoDrawable.FBO)
factory.createOffscreenAutoDrawable(null, capabilities, null, pg.width, pg.height, null);
final FBObject fboBack  = glad.getFBObject(GL.GL_BACK);
final FBObject.TextureAttachment texAttachA = glad.getTextureBuffer(GL.GL_FRONT);
final FBObject.TextureAttachment texAttachB = glad.getTextureBuffer(GL.GL_BACK);

but the FBO and texture attachment objects are null. I imagine this is because the GL context is still not initialized at that point. In the unit test I see you force the initialization by calling glad.display(), if I insert that call right after GLOffscreenAutoDrawable.FBO glad = ... I get this error:

Exception in thread "Animation Thread" java.lang.IllegalArgumentException: Cannot access GL_BACK buffer of MSAA FBO: ResizeableImpl[Initialized true, realized true, texUnit 0, samples 2,
        Factory   jogamp.opengl.macosx.cgl.awt.MacOSXAWTCGLDrawableFactory@564ac216,
        Handle    0x1001fb390,
        ....

But shouldn't I be getting the GLOffscreenAutoDrawable.FBO in the display method of the GLEventListener itself? However all I have in GLEventListener.display() is the GLAutoDrawable object, which it seems I cannot cast or use to get the underlying GLOffscreenAutoDrawable.FBO...
Reply | Threaded
Open this post in threaded view
|

Re: querying textures bound to default draw/read framebuffers

Sven Gothel
Administrator
On 10/20/2012 03:02 PM, ac [via jogamp] wrote:

> Hello Sven, thanks for your reply. All this new API to handle the FBOs looks
> great, but I'm still unsure how to properly integrate with my old code. I've
> been looking at TestFBOAutoDrawableFactoryNEWT.java, and I think I understand
> how the unit tests work. Based on that, I added the following code at the end
> of my JOGL initialization function (where I create the request capabilities,
> the canvas object, etc):
>
> final GLDrawableFactory factory = GLDrawableFactory.getFactory(profile);
> GLOffscreenAutoDrawable.FBO glad = (GLOffscreenAutoDrawable.FBO)
> factory.createOffscreenAutoDrawable(null, capabilities, null, pg.width,
> pg.height, null);
> final FBObject fboBack  = glad.getFBObject(GL.GL_BACK);
> final FBObject.TextureAttachment texAttachA = glad.getTextureBuffer(GL.GL_FRONT);
> final FBObject.TextureAttachment texAttachB = glad.getTextureBuffer(GL.GL_BACK);
>
> but the FBO and texture attachment objects are null. I imagine this is because
> the GL context is still not initialized at that point.
Yes, and this is documented in the API .. read:
  <http://jogamp.org/deployment/archive/master/gluegen_600-joal_366-jogl_833-jocl_691-signed/javadoc/jogl/javadoc/javax/media/opengl/GLFBODrawable.html>
I agree .. maybe a bit hidden :)
The unit test mentions the same.
  <http://jogamp.org/git/?p=jogl.git;a=blob;f=src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableFactoryNEWT.java;h=2dc547f39b55a2f0541a960a41bbb9437f78834c;hb=HEAD#l152>

Maybe you can open a new bug entry for FBO enhancements,
where we can mention all these weak points
to have a chance to enhance it!

> In the unit test I see
> you force the initialization by calling glad.display(), if I insert that call
> right after GLOffscreenAutoDrawable.FBO glad = ... I get this error:
>
> Exception in thread "Animation Thread" java.lang.IllegalArgumentException:
> Cannot access GL_BACK buffer of MSAA FBO: ResizeableImpl[Initialized true,
> realized true, texUnit 0, samples 2,
>         Factory  
> jogamp.opengl.macosx.cgl.awt.MacOSXAWTCGLDrawableFactory@564ac216,
>         Handle    0x1001fb390,
>         ....
Read:
  <http://jogamp.org/deployment/archive/master/gluegen_600-joal_366-jogl_833-jocl_691-signed/javadoc/jogl/javadoc/javax/media/opengl/GLFBODrawable.html#getTextureBuffer%28int%29>
"If MSAA is being used, only the GL.GL_FRONT buffer is accessible and an exception is being thrown if GL.GL_BACK is being requested."

As you know, there is not readable BACK buffer w/ MSAA, i.e. the buffer we render into,
only the sampled front buffer texture.
The same GL error will happen if attempting to read an FBO BACK buffer,
since it must be blitted. (You showed me that code sample once)
Well, you can get the FBObject though.

>
> But shouldn't I be getting the GLOffscreenAutoDrawable.FBO in the display
> method of the GLEventListener itself? However all I have in
> GLEventListener.display() is the GLAutoDrawable object, which it seems I
> cannot cast or use to get the underlying GLOffscreenAutoDrawable.FBO...

Sure you can cast it, why not ?
Well, we don't use the 'sophisticated' generics stuff here
due to history and .. well, is it really that good looking ? :)
But since you know what you have created you sure can cast,
and/or use reflection/instanceof.
You even can simply query a GLAutoDrawable's chosen Capabilities
and if it says isFBO()==true .. you should be safe.

However .. since this new API is now critical to JOGL
due to it's usage in all core classes and especially on OSX,
I love to see it being enhanced (See bug/enhancements above).

~Sven



signature.asc (907 bytes) Download Attachment
ac
Reply | Threaded
Open this post in threaded view
|

Re: querying textures bound to default draw/read framebuffers

ac
Ok, I think I'm on track now. If using AWT, then I can do:

  protected class PGLListener implements GLEventListener {
    @Override
    public void display(GLAutoDrawable adrawable) {
        GLCanvas canvas = (GLCanvas)adrawable;
        GLFBODrawable drawable = (GLFBODrawable)canvas.getDelegatedDrawable();
        ...

and the name of the texture bound to the front FBO can be obtained with:

FBObject.TextureAttachment texFront = drawable.getTextureBuffer(GL.GL_FRONT);
System.out.println("front texture: " + texFront.getName());

Is this correct?

But another route seems to be:

FBObject fboFront = drawable.getFBObject(GL.GL_FRONT);
System.out.println("number of color attachements: " + fboFront.getColorAttachmentCount());

(prints 1, as expected). But then, how can I get the texture name from here? FBObject has getDepthAttachment() and getStencilAttachment() methods, but not a getColorAttachement()...

Should just I use GLFBODrawable.getTextureBuffer()?
ac
Reply | Threaded
Open this post in threaded view
|

Re: querying textures bound to default draw/read framebuffers

ac
I found it, I only need to cast the color buffer object as a TextureAttachment:

FBObject fboFront = dr.getFBObject(GL.GL_FRONT);
FBObject.Colorbuffer colorBuf = fboFront.getColorbuffer(0);
FBObject.TextureAttachment texFront = (FBObject.TextureAttachment) colorBuf;
System.out.println("front texture: " + texFront.getName());

which seems to be equivalent to FBObject.TextureAttachment texFront = drawable.getTextureBuffer(GL.GL_FRONT). Which method is preferred?

Also, in terms of API, it seems to me that FBObject should have a getColorAttachment() method which returns a FBO.ColorAttachment. The texture name could be also queried from it, since it has a name property. Although this lead to three different ways of getting the name of the bound texture.

Another question: what should I do if I need to blit the contents of the multisampled back buffer into the front buffer mid-render when using MSAA? Just call swapBuffers()?
Reply | Threaded
Open this post in threaded view
|

Re: querying textures bound to default draw/read framebuffers

Sven Gothel
Administrator
On 10/20/2012 07:23 PM, ac [via jogamp] wrote:

> I found it, I only need to cast the color buffer object as a TextureAttachment:
>
> FBObject fboFront = dr.getFBObject(GL.GL_FRONT);
> FBObject.Colorbuffer colorBuf = fboFront.getColorbuffer(0);
> FBObject.TextureAttachment texFront = (FBObject.TextureAttachment) colorBuf;
> System.out.println("front texture: " + texFront.getName());
>
> which seems to be equivalent to FBObject.TextureAttachment texFront =
> drawable.getTextureBuffer(GL.GL_FRONT). Which method is preferred?
>
> Also, in terms of API, it seems to me that FBObject should have a
> getColorAttachment() method which returns a FBO.ColorAttachment. The texture
> name could be also queried from it, since it has a name property. Although
> this lead to three different ways of getting the name of the bound texture.
>
FBObject's is more generic (texture or w/o, i.e. 'just' colorbuffer),
where GLFBODrawable always uses it w/ textures only - hence the slight API delta.

> Another question: what should I do if I need to blit the contents of the
> multisampled back buffer into the front buffer mid-render when using MSAA?
> Just call swapBuffers()?

From the GLFBODrawable perspective yes ofc, it's completely transparent,
and uses for OSX CALayer for example, see unit tests w/ auto GLFBODrawables:
  TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT
  <http://jogamp.org/git/?p=jogl.git;a=blob;f=src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java;h=da54567771d880daab83eb7fe2e903b21fdd78fa;hb=HEAD>

  TestGLAutoDrawableDelegateOnOffscrnCapsNEWT
  <http://jogamp.org/git/?p=jogl.git;a=blob;f=src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.java;h=d9e9b2bf340ece3d9f4dd61a4ef2fd256d659fd8;hb=HEAD>

Just select FBO in caps, done deal.

Internally (GLFBODrawable) you will see that we intercept
the swapBuffer signal and issue syncSamplingSink()
  <http://jogamp.org/deployment/archive/master/gluegen_600-joal_366-jogl_833-jocl_691-signed/javadoc/jogl/javadoc/com/jogamp/opengl/FBObject.html#syncSamplingSink%28javax.media.opengl.GL%29>
besides buffer swapping (check the source).

~Sven



signature.asc (907 bytes) Download Attachment
ac
Reply | Threaded
Open this post in threaded view
|

Re: querying textures bound to default draw/read framebuffers

ac
Thanks. I'm trying to get the contents of the texture used as the sink of the MSAA rendering, but still having some issues (for example, rendering the texture results in garbage). My final goal consists in grabbing the contents of the screen at a specific time, and applying a post-processing shader to it.

The following is a simplified snippet of the display() function in my GLEventListener:

public void display(GLAutoDrawable drawable) {
  GLCanvas canvas = (GLCanvas)drawable;
  GLContext context = drawable.getContext();
  GL gl = context.getGL();

  // Obtain the texture used a MSAA sink:
  GLFBODrawable  fboDrawable = (GLFBODrawable)canvas.getDelegatedDrawable();
  FBObject backFbo = fboDrawable.getFBObject(GL.GL_BACK);  
  FBObject.TextureAttachment texAttach = fboBack.getSamplingSink();

  // Draw geometry... *

  fboBack.syncSamplingSink(gl);
  fboBack.bind(gl);

  // Now texAttach should be up-to-date with the geometry rendered in (*)

  ...

Do you see anything drastically wrong here?
Reply | Threaded
Open this post in threaded view
|

Re: querying textures bound to default draw/read framebuffers

Sven Gothel
Administrator
On 10/24/2012 04:47 AM, ac [via jogamp] wrote:
> Thanks. I'm trying to get the contents of the texture used as the sink of the
> MSAA rendering, but still having some issues (for example, rendering the
> texture results in garbage). My final goal consists in grabbing the contents
> of the screen at a specific time, and applying a post-processing shader to it.
>
> The following is a simplified snippet of the display() function in my
> GLEventListener:

> Do you see anything drastically wrong here?

Why don't you simply use the FRONT texture/FBO after rendering
content and sync the FBO ?
Again, the BACK of an MSAA FBO only has a
multisampled [unusable] colorbuffer not a texture
and cannot be used (due to the OpenGL framebuffer spec).

After sampling w/ syncSamplingSink() you can use the FRONT texture.

Also be aware that the GLFBOAutoDrawable's intent is to handle swap-buffer
and hence deliver the final image. Ofc you can circumvent this by disabling
auto-swap buffer. Below I mention a manual swap-buffer step.

It would be more clear if you can produce a small complete unit test
stating your goals.

There is for example a unit test which mixes 2 GLFBODrawable's:
  TestFBOMix2DemosES2NEWT/FBOMix2DemosES2.
The 'inner' offscreen mix source drawables are FBObject and could be
GLFBODrawables ofc. The outer drawable is an auto drawable (FBO or onscreen, doesn't matter).

However .. I try to comment a bit on your code snippet,
maybe it helps:

> public void display(GLAutoDrawable drawable) {
>   GLCanvas canvas = (GLCanvas)drawable;
>   GLContext context = drawable.getContext();
>   GL gl = context.getGL();
>
>   // Obtain the texture used a MSAA sink:
>   GLFBODrawable  fboDrawable = (GLFBODrawable)canvas.getDelegatedDrawable();
>   FBObject backFbo = fboDrawable.getFBObject(GL.GL_BACK);  
backFbo is the sampling sink, you want FRONT !

Note, FRONT is the last frame's content !

>   FBObject.TextureAttachment texAttach = fboBack.getSamplingSink();

>
>   // Draw geometry... *
>
>   fboBack.syncSamplingSink(gl);
>   fboBack.bind(gl);
>
>   // Now texAttach should be up-to-date with the geometry rendered in (*)
>
>   ...

If you don't want to use the last frames content (see snippet below),
but this frames .. you simply need to swap 'one more time'
which also will sample the content.
This is only required if both rendering contents shall be sampled,
otherwise I would use another drawable target!

public void display(GLAutoDrawable drawable) {
   GLContext context = drawable.getContext();
   GL gl = context.getGL();

   // Draw some stuff 1

   // This will do the BACK -> FRONT swap
   // including MSAA sampling (sync).
   // Now we can use the FRONT buffer.
   drawable.swapBuffer();
 
   // Obtain the texture used a MSAA sink:
   // getDelegatedDrawable() is specified in GLAutoDrawable!
   final GLFBODrawable  fboDrawable = (GLFBODrawable)drawable.getDelegatedDrawable();
   final TextureAttachment texAttach = fboDrawable.getTextureBuffer (GL.GL_FRONT);

   gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit); // DO THAT IF USING MULTI TEX UNITS ..
   gl.glBindTexture(GL.GL_TEXTURE_2D, texAttach.getName()); // use it ..
   gl.glEnable(GL.GL_TEXTURE_2D); // if not using ES2 or GLSL!!
   // now texUnit / texAttach is being used for texturing

   // use prev. frame texture ..
   // Draw some stuff 2  
}  

The swapBuffer() will be issued within the current context
and (w/ _latest_ JOGL code) will not issue a recursive call w/ GLDrawableHelper
but use a direct call of the drawable.swapBuffer().


+++

Let's try a simple use case, where you want to reuse
the FRONT buffer of the prev. frame while rendering the current frame.
This way you could to some motion blur or whatever ..

It is important to understand the 'timing' detail,
i.e. front/back buffers and when what get synced/swapped!
 
public void display(GLAutoDrawable drawable) {
   GLContext context = drawable.getContext();
   GL gl = context.getGL();
 
   // Draw some stuff 1
 
   // Obtain the texture used a MSAA sink:
   // getDelegatedDrawable() is specified in GLAutoDrawable!
   final GLFBODrawable  fboDrawable = (GLFBODrawable)drawable.getDelegatedDrawable();
   final TextureAttachment texAttach = fboDrawable.getTextureBuffer (GL.GL_FRONT);
   gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit); // DO THAT IF USING MULTI TEX UNITS ..
   gl.glBindTexture(GL.GL_TEXTURE_2D, texAttach.getName()); // use it ..
   gl.glEnable(GL.GL_TEXTURE_2D); // if not using ES2 or GLSL!!
   // now texUnit / texAttach is being used for texturing

   // use prev. frame texture ..
   // Draw some stuff 2  
}
 
+++

Hope this helps a bit.

~Sven


signature.asc (907 bytes) Download Attachment
ac
Reply | Threaded
Open this post in threaded view
|

Re: querying textures bound to default draw/read framebuffers

ac
I finally made it work by calling syncSamplingSink on the back buffer, and reading the front texture. Thanks for the detailed instructions!