setOffscreenRenderToTexture

Hello

i try to use the RendertoTexture in Jogl and get some starting problems

GLAutoDrawable make some problem i didnt understand
in creating the pbuffer,it says it need GLDrawable, but when i
change it at init the rest of the init makes problem
(this for example GL gl = arg0.getGL(); )

and how i create the pbuffer texture itself?


public void init(GLAutoDrawable arg0) 
    {
		 

  GL gl = arg0.getGL();
 if (gl.isExtensionAvailable("WGL_ARB_pbuffer"))  //  perfect ARB_pbuffer supported
      {
      System.out.println("pbuffer SUPPORTED");
      pbuf=1;


      boolean supported = arg0.canCreateOffscreenDrawable(); 
 //GLAutoDrawable is the problem, with GLDrawable at init the rest is not working

      GLCapabilities caps = new GLCapabilities();
      caps.setOffscreenRenderToTexture(true);            //error
      caps.setDoubleBuffered(false); 
...



I’m pretty sure that you want to create a GLCapabilities object before you start rendering anything with you GLAutoDrawable or GLDrawable instead of creating on in your init method. Also, there should be a factory for creating pbuffers that you can use.

i got some problems understanding the function

  1. checking and initalizing
  2. create render target
  3. use/switch render target

using the search function confuses me more and more
with the examples i see

ok, the factory thing must be bevor initpart


GLU glu = new GLU();
canvas = new GLCanvas(cap);
canvas.addGLEventListener(new SceneView());
getContentPane().add(canvas);
setTitle(“demo”);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

there is one example in jogl site …but i didnt understand it

is there any threat/posting with a full description of it?

I strongly recommend you avoid the setOffscreenRenderToTexture bit and instead use Frame Buffer Objects instead. Pbuffer render-to-texture functionality is not portable, while FBOs are, and FBOs are pretty well supported by most graphics cards at this point.

i need the app the run on nearly all systems, so the FBO seems to be a better way

i think i got the initzalisation of the fbo


GL gl = arg0.getGL();
gl.glGenFramebuffersEXT(1, fbo, 0); 
gl.glBindFramebufferEXT (GL.GL_FRAMEBUFFER_EXT, fbo[0]);
gl.glBindRenderbufferEXT( GL.GL_RENDERBUFFER_EXT, fbo[0] );
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glOrtho(-100, 100, -100, 100, -100, 100);
setCamera(1,gl,glu,0,0,0,view_r1,view_r2); 
gl.glViewport(0, 0, 256, 256);

and with :
gl.glBindFramebufferEXT (GL.GL_FRAMEBUFFER_EXT, 0);
gl.glBindRenderbufferEXT( GL.GL_RENDERBUFFER_EXT, 0 );
…i switch back

my question, how can i use the fbo[0] as a texture
and is there anything missing at the first look?

the app is running, but when i for example render the scene with target
fbo[0] (glbindframebuffer/renderbufferext) the screen appears black.
so i dont know if the scene is rendered succsesful in the fbo[0].

thanks for any reply

You have to add a color attachement to the framebuffer, which will be the texture you will draw to. A quick google run found two introductional FBO articles, unfortunately not for jogl, but you should be able to find the needed clues for you in them:

this one is for C: http://www.gamedev.net/reference/articles/article2331.asp
this one for LWJGL: http://lwjgl.org/wiki/doku.php/lwjgl/tutorials/opengl/basicfbo

i am in big trouble

i try to work with the gamedev example, but my problem
is that i am not good in converting code from other
languages

i commented in my code the problems,
i take the original code, but there appear the problem that in jogl
example :i need depthbuffer as int and the next line the depthbuffer must be an IntBuffer ?!?!)

i think fbo are really not easy to use,
i cant find any code of anybody that use fbo in jogl


 public void initFBO(GLAutoDrawable arg0){
		
		 int fbo_width=256;
		 int fbo_height=256;
		 
		    GL gl = arg0.getGL();
		    gl.glGenFramebuffersEXT(1, fb, 0); 
		   
		    gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, fb[0]);
		    
		    
		    IntBuffer depthbuffer;
		    gl.glGenRenderbuffersEXT(1, depthbuffer);
		    
            //this one show error,  simple INT wanted?!?!
		    gl.glBindRenderbufferEXT( GL.GL_RENDERBUFFER_EXT, depthbuffer);
			  
		    
		    gl.glRenderbufferStorageEXT(GL.GL_RENDERBUFFER_EXT, GL.GL_DEPTH_COMPONENT, fbo_width, fbo_height);
		    
		    gl.glFramebufferRenderbufferEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_DEPTH_ATTACHMENT_EXT, GL.GL_RENDERBUFFER_EXT, fb[0]);
		    
		    
		    
		    IntBuffer img;
		    gl.glGenTextures(1, img);

          //here the same int versus intbuffer problem		   
                               gl.glBindTexture(GL.GL_TEXTURE_2D,  img);


		    gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA8,  fbo_width, fbo_height, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, 0);
		    
		    
		    gl.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_COLOR_ATTACHMENT0_EXT, GL.GL_TEXTURE_2D, 0, 0);
			  

		    

Not that big of trouble yet ;)…

[quote]i try to work with the gamedev example, but my problem
is that i am not good in converting code from other
languages

i commented in my code the problems,
i take the original code, but there appear the problem that in jogl
example :i need depthbuffer as int and the next line the depthbuffer must be an IntBuffer ?!?!)
[/quote]
You’re on the right track, and actually the crux of your problem is the converting from one language to another.

IntBuffer depthBuffer = BufferUtils.IntBuffer(1); //Really bad psuedo code here, go look up the buffer utils in the jogl java docs
IntBuffer fbo = BufferUtils.IntBuffer(1);

gl.glGenFramebuffersEXT(1, fbo);
gl.glGenRenderbuffersEXT(1, depthBuffer);
gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, fbo.get(0));
gl.glBindRenderbufferEXT( GL.GL_RENDERBUFFER_EXT, depthbuffer.get(0));

and I hope that should be enough to help you get back up to speed.

[quote]i think fbo are really not easy to use,
i cant find any code of anybody that use fbo in jogl
[/quote]
FBOs are a massive improvement over PBuffers, but when they’re new to you it’s all a steep learning curve.

much thanks for the help,

i read the docs of Utils and i get a big step , i think
i am close to it.



....
int[] rendertex = new int[1];
IntBuffer depthBuffer = BufferUtil.newIntBuffer(1);
IntBuffer fbo         = BufferUtil.newIntBuffer(1);
....

public void initFBO(GLAutoDrawable arg0){
		
		    int fbo_width=256;
		    int fbo_height=256;
		 
		    GL gl = arg0.getGL();
		     
		   
		    gl.glGenFramebuffersEXT(1, fbo); 
		    gl.glGenRenderbuffersEXT(1, depthBuffer); 
		    gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, fbo.get(0));
		    gl.glBindRenderbufferEXT( GL.GL_RENDERBUFFER_EXT, depthbuffer.length);
		    
 
		    gl.glRenderbufferStorageEXT(GL.GL_RENDERBUFFER_EXT, GL.GL_DEPTH_COMPONENT, fbo_width, fbo_height);	    
		    gl.glFramebufferRenderbufferEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_DEPTH_ATTACHMENT_EXT, GL.GL_RENDERBUFFER_EXT, fbo.get(0));

       
		    gl.glGenTextures(1, rendertex,0);
	                 int textureID = rendertex[0];

	                 gl.glBindTexture(GL.GL_TEXTURE_2D, textureID);
	    
	                 gl.glTexImage2D(GL.GL_TEXTURE_2D, 
	                 0, 
	                 GL.GL_RGB,
	                 fbo_width, 
	                 fbo_height,
	                 0,
	                 GL.GL_BGRA, 
	                 GL.GL_UNSIGNED_BYTE, 
	                 null);
	        
	                gl.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_COLOR_ATTACHMENT0_EXT, GL.GL_TEXTURE_2D, 0, 0);
			
...



I noticed just a couple of things, the compiler won’t catch these…
gl.glBindRenderbufferEXT( GL.GL_RENDERBUFFER_EXT, depthbuffer.length);
should be…
gl.glBindRenderbufferEXT( GL.GL_RENDERBUFFER_EXT, depthbuffer.get(0));

and

	    gl.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_COLOR_ATTACHMENT0_EXT, GL.GL_TEXTURE_2D, 0, 0);

should be…
gl.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_COLOR_ATTACHMENT0_EXT, GL.GL_TEXTURE_2D, textureID, 0);

much thanks,
i changed the code.

i start a little test with
init the fbo, set up a clear color
and inside my game
render an object with the fbo texture .

result, a gray color. i was hoping that the
color i see inside the game on the object
is the same linke the clearcolor in the fbo init,
but its not changing so i think its not working
at moment

here are my complete init_fbo code and the command lines i use for bind the fbo texture

public void initFBO(GLAutoDrawable arg0){
		
		    int fbo_width=256;
		    int fbo_height=256;
		 
		    GL gl = arg0.getGL();
		    	    
		    gl.glGenFramebuffersEXT(1, fbo); 
		    gl.glGenRenderbuffersEXT(1, depthBuffer); 
		    gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, fbo.get(0));
		    gl.glBindRenderbufferEXT( GL.GL_RENDERBUFFER_EXT, depthBuffer.get(0));
 
		    gl.glRenderbufferStorageEXT(GL.GL_RENDERBUFFER_EXT, GL.GL_DEPTH_COMPONENT, fbo_width, fbo_height);	    
		    gl.glFramebufferRenderbufferEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_DEPTH_ATTACHMENT_EXT, GL.GL_RENDERBUFFER_EXT, fbo.get(0));

       
		    gl.glGenTextures(1, rendertex,0);
	        int textureID = rendertex[0];

	        gl.glBindTexture(GL.GL_TEXTURE_2D, textureID);
	    
	        gl.glTexImage2D(GL.GL_TEXTURE_2D, 
	                0, 
	                GL.GL_RGBA8,
	                fbo_width, 
	                fbo_height,
	                0,
	                GL.GL_RGBA, 
	                GL.GL_UNSIGNED_BYTE, 
	                null);
	        
	        gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE);
	        gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE);
	        gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
	        gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR_MIPMAP_LINEAR);
      
	        gl.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_COLOR_ATTACHMENT0_EXT, GL.GL_TEXTURE_2D, textureID, 0);
		  
	        
//use FBO
	        gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, fbo.get(0));
	        gl.glPushAttrib(GL.GL_VIEWPORT_BIT);
	       
                     gl.glViewport(0,0,fbo_width, fbo_height);


//set up a clear color for a fast test

	        gl.glEnable(GL.GL_AUTO_NORMAL);
	        gl.glClearColor(0.0f, 0.9f, 0.0f, 0.0f);
	        gl.glColor3f(0.0f, 0.0f, 1.0f);

	
	        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
	        GLU glu = new GLU();
	        
	 	 	FloatBuffer  ambient = BufferUtil.newFloatBuffer(4);
	  	 	ambient.put(0.1f);
	  	 	ambient.put(0.1f);
	  	 	ambient.put(0.1f);
	  	 	ambient.put(0.1f);
	  	  	ambient.rewind();
	  	
	  	 gl.glLightModelfv( GL.GL_LIGHT_MODEL_AMBIENT, ambient );
	              gl.glClearColor(0.0f, 1.0f, 1.0f, 0.0f);
	              gl.glMatrixMode(GL.GL_PROJECTION);
	              gl.glOrtho(-100, 100, -100, 100, -100, 100);
	      
	        gl.glMatrixMode( GL.GL_PROJECTION );
	        gl.glLoadIdentity();
		  
                     glu.gluPerspective( 45.0, fbo_width / fbo_height, 0.1, 20000.0 );
	  
	        gl.glPopAttrib();
	        gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 0);
}

int textureID = rendertex[0];
gl.glBindTexture(GL.GL_TEXTURE_2D, textureID);
render_my_objekt...

There are far to many possible avenues that things may have gone wrong for me to try and help while at work. But if you check back semi-regularly through the weekend I’ll see about writing up a simple little FBO demo to help illustrate how they work and how to use them.

No promises on my code being 100% correct but it works on my system. And Ken if you wanted to include this code or any derivative of it into the jogl demos by all means feel free to.

import java.awt.*;
import java.awt.event.*;
import java.nio.*;

import javax.media.opengl.*;
import javax.media.opengl.glu.*;
import com.sun.opengl.util.*;

public class SimpleFBODemo implements GLEventListener
{
	private static Frame frame;
    private static GLCanvas canvas;
    private static int height = 600;
    private static int width = 800;
    private IntBuffer texture;
    private IntBuffer fbo;
    private IntBuffer depth;

    public static void main(String args[])
    {        
    	frame = new Frame("Super Simple JOGL FBO Demo");
        frame.setSize(width, height);
        
        SimpleFBODemo dc = new SimpleFBODemo();
        canvas = new GLCanvas();
        canvas.addGLEventListener(dc);
        
        frame.add(canvas);
        frame.setVisible(true);
        
        final Animator animator = new Animator(canvas);
        frame.addWindowListener(new WindowAdapter()
        {
            public void windowClosing(WindowEvent e)
            {animator.stop(); System.exit(0);}
        });
        animator.start();
    }
    
    public SimpleFBODemo(){}    
    public void displayChanged(GLAutoDrawable drawable, boolean arg1, boolean arg2){}
	public void reshape(GLAutoDrawable drawable, int arg1, int arg2, int arg3, int arg4){}
    
	public void init(GLAutoDrawable drawable)
	{
		GL gl = drawable.getGL();
        GLU glu = new GLU();
        
        gl.glMatrixMode(GL.GL_PROJECTION);
        gl.glLoadIdentity();
        glu.gluPerspective(75.0f, 1.0, 1.0f, 100.0f);
        
        gl.glMatrixMode(GL.GL_MODELVIEW);
        gl.glLoadIdentity();
        
        initializeFBO(drawable);
	}
	
	public void initializeFBO(GLAutoDrawable drawable)
	{
		GL gl = drawable.getGL();

        fbo = BufferUtil.newIntBuffer(1);
        depth = BufferUtil.newIntBuffer(1);
        texture = BufferUtil.newIntBuffer(1);
        
        gl.glGenFramebuffersEXT(1, fbo);
        gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, fbo.get(0));
        
        // !!! Don't mess with stencil or combined depth/stencil
        // !!! until you really know what you're doing.
        // !!! They're poorly supported at the moment.
        gl.glGenRenderbuffersEXT(1, depth);
        gl.glBindRenderbufferEXT(GL.GL_RENDERBUFFER_EXT, depth.get(0));
        gl.glRenderbufferStorageEXT(GL.GL_RENDERBUFFER_EXT, GL.GL_DEPTH_COMPONENT24, width, height);
        gl.glBindRenderbufferEXT(GL.GL_RENDERBUFFER_EXT, 0);
        gl.glFramebufferRenderbufferEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_DEPTH_ATTACHMENT_EXT, GL.GL_RENDERBUFFER_EXT, depth.get(0));

        gl.glGenTextures(1, texture);
        gl.glBindTexture(GL.GL_TEXTURE_2D, texture.get(0));
        gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
        gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
        gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE);
        gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, width, height, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, null);
        
        //Just for good measure, not actually used yet
        gl.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_COLOR_ATTACHMENT0_EXT, GL.GL_TEXTURE_2D, texture.get(0), 0);
        gl.glBindTexture(GL.GL_TEXTURE_2D, 0);

        int status = gl.glCheckFramebufferStatusEXT(GL.GL_FRAMEBUFFER_EXT);
        if(status != 0x8CD5)
        {
            if(status == 0x8CD6)
            {
                System.err.println("FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT");
            }
            else if(status == 0x8CD7)
            {
                System.err.println("FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT");
            }
            else if(status == 0x8CD9)
            {
                System.err.println("FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT");
            }
            else if(status == 0x8CDA)
            {
                System.err.println("FRAMEBUFFER_INCOMPLETE_FORMATS_EXT");
            }
            else if(status == 0x8CDB)
            {
                System.err.println("FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT");
            }
            else if(status == 0x8CDC)
            {
                System.err.println("FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT");
            }
            else if(status == 0x8CDD)
            {
                System.err.println("FRAMEBUFFER_UNSUPPORTED_EXT");
            }
            else
            {
                System.err.println("Unknown framebuffer error: " + Integer.toHexString(status));
            }
        }
        
        //Bind back to the primary display
        gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 0);
	}
	
	public void display(GLAutoDrawable drawable)
	{
		GL gl = drawable.getGL();
        
        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
        
        drawToFBO(drawable);
        drawToPrimary(drawable);
	}
	
	public void drawToFBO(GLAutoDrawable drawable)
	{
		GL gl = drawable.getGL();
		GLUT glut = new GLUT();
		
		//Need to disable the texture, and either approach works
		gl.glDisable(GL.GL_TEXTURE_2D);//Disable texturing
		//gl.glBindTexture(GL.GL_TEXTURE_2D, 0);//Bind to a different texture
		
		gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, fbo.get(0));
		
		gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);//Black
		gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
		
		//Can actually do what ever drawing you wanted here
		//but I'm trying to keep it simple
		
		gl.glLineWidth(5.0f);//Make the sphere a little easier to see
		gl.glColor3f(1.0f, 1.0f, 0.0f);
		
		//Actual drawing
		gl.glPushMatrix();
        gl.glTranslatef(0.0f, 0.0f, -4.0f);
        	glut.glutWireSphere(2.5f, 20, 20);
        gl.glPopMatrix();
	}
	
	public void drawToPrimary(GLAutoDrawable drawable)
	{
		GL gl = drawable.getGL();
		gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 0);
		
		gl.glClearColor(0.0f, 0.0f, 1.0f, 1.0f);//Blue
		gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
		
		gl.glPushMatrix();
		gl.glTranslatef(0.0f, 0.0f, -4.0f);
		gl.glRotatef(45.0f, 0.0f, 1.0f, 0.0f);//Just to illustrate that it's texturing
		
		//Need to bind and enable the texture as per normal
		gl.glBindTexture(GL.GL_TEXTURE_2D, texture.get(0));
		gl.glEnable(GL.GL_TEXTURE_2D);
		
		//Can actually do what ever drawing you wanted here
		//but I'm trying to keep it simple
		
		gl.glBegin(GL.GL_QUADS);
        	gl.glColor3f(0.0f, 1.0f, 0.0f);
        	
        	gl.glTexCoord2f(0.0f, 0.0f);
	        gl.glVertex3f(-1.0f, -1.0f, 0.0f);
	        
	        gl.glTexCoord2f(0.0f, 1.0f);
	        gl.glVertex3f(1.0f, -1.0f, 0.0f);
	        
	        gl.glTexCoord2f(1.0f, 1.0f);
	        gl.glVertex3f(1.0f, 1.0f, 0.0f);
	        
	        gl.glTexCoord2f(1.0f, 0.0f);
	        gl.glVertex3f(-1.0f, 1.0f, 0.0f);
        gl.glEnd();
		
        gl.glPopMatrix();
	}
}

fantastic… absolut wonderful :slight_smile:

its working perfect

one litte change was to do inside the code…
the

private IntBuffer texture;
private IntBuffer fbo;
private IntBuffer depth;

i needed to change to:

IntBuffer fbo = BufferUtil.newIntBuffer(1);
IntBuffer depth = BufferUtil.newIntBuffer(1);
IntBuffer fbo_texture = BufferUtil.newIntBuffer(1);

and the name texture was making some trouble…after changing
the name to fbo_texture in the codewas all running perfect

much much much much much thanks for your great example

:slight_smile:

I would like to add it to Netbeans OpenGL Pack if you don’t mind?

And you’re very welcome.

That would be fine with me so long as it didn’t preclude its inclusion into the JOGL demos if it was desired.

There are no restrictions to include your sample anywhere else if you would ship it with the NetBeans OpenGL Pack. Since we are also bundling the JOGL demos, I personally don’t care where your code finally ends. (its a win-win situation for us ;D)

maybe we should wait until Ken is back. You could choose the pack as fallback mode :wink:

It’s fine with me if it ends up in both places, I just want that if licensing is an issue (which I admittedly know next to nothing about), priority goes to the JOGL demos. Otherwise by all means the NetBeans pack is welcome to it.

There are no licensing issues. Chris, have you signed the Sun Contributor Agreement?