LWJGL Forum

Programming => OpenGL => Topic started by: Wolftein on November 28, 2009, 19:05:56

Title: [Help]: FBO Issues.
Post by: Wolftein on November 28, 2009, 19:05:56
Hello.. Im Using an fbo for rendering my scene to texture but i have a problem. When i render a normal texture to the screen, the texture renders fine, but when i render the fbo to the screen its render wierd, its like the fbo its rotated 90 degrees..

Opengl Property
Code: [Select]
        // Enable texturing 2D
        GL11.glEnable( GL11.GL_TEXTURE_2D );
        // Calculate The Aspect Ratio Of The Window
        GL11.glViewport( 0, 0, iViewPortX, iViewPortY );
        GL11.glMatrixMode( GL11.GL_PROJECTION ); // Select The Projection Matrix
        GL11.glLoadIdentity( ); // Reset The Projection Matrix
        GL11.glOrtho( 0.0f, iWidth, iHeight, 0.0f, -1.0f, 1.0f );
        GL11.glMatrixMode( GL11.GL_MODELVIEW ); // Select The Modelview Matrix
        GL11.glLoadIdentity( );
        // Disable ZBuffer
        GL11.glDisable( GL11.GL_DEPTH_TEST );
        GL11.glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );

Render
Code: [Select]
    static private void Renderizable( Texture Texture, int iX, int iY, float fSourceX,
                                      float fSourceY, float fWidth, float fHeight )
    {
        // Get the texture property
        int imageWidth = Texture.GetImageWidth( ), imageHeight = Texture.GetImageHeight( );
        float imageClampedWidth = Texture.GetWidth( ), imageClampedHeight = Texture.GetHeight( );

        // Bind the Texture for rendering.
        Texture.Bind( );
        // Generate Texture Mapping
        float minX = (fSourceX / imageWidth) * imageClampedWidth;
        float minY = (fSourceY / imageHeight) * imageClampedHeight;
        float maxX = ((fSourceX + fWidth - 1.0f) / imageWidth) * imageClampedWidth;
        float maxY = ((fSourceY + fHeight - 1.0f) / imageHeight) * imageClampedHeight;
        // Direct Rendering to the opengl driver.
        GL11.glBegin(GL11.GL_TRIANGLE_STRIP);
             GL11.glTexCoord2f( minX, minY); GL11.glVertex2f( iX, iY );
             GL11.glTexCoord2f( minX, maxY); GL11.glVertex2f( iX, iY + fHeight );
             GL11.glTexCoord2f( maxX, minY); GL11.glVertex2f( iX + fWidth, iY );
             GL11.glTexCoord2f( maxX, maxY); GL11.glVertex2f( iX + fWidth, iY + fHeight );
        GL11.glEnd();
    }

And here is the problem.

(http://img132.imageshack.us/img132/7687/fborendering.jpg)
Title: Re: [Help]: FBO Issues.
Post by: broumbroum on November 28, 2009, 23:27:39
Code: [Select]
GL11.glBegin(GL11.GL_TRIANGLE_STRIP);
             GL11.glTexCoord2f( minX, minY); GL11.glVertex2f( iX, iY );
             GL11.glTexCoord2f( minX, maxY); GL11.glVertex2f( iX, iY + fHeight );
             GL11.glTexCoord2f( maxX, maxY); GL11.glVertex2f( iX + fWidth, iY + fHeight ); //  invert these 2 lines
             GL11.glTexCoord2f( maxX, minY); GL11.glVertex2f( iX + fWidth, iY ); // for proper CCW vertexes
        GL11.glEnd();
Title: Re: [Help]: FBO Issues.
Post by: Wolftein on November 29, 2009, 18:56:15
Code: [Select]
GL11.glBegin(GL11.GL_TRIANGLE_STRIP);
             GL11.glTexCoord2f( minX, minY); GL11.glVertex2f( iX, iY );
             GL11.glTexCoord2f( minX, maxY); GL11.glVertex2f( iX, iY + fHeight );
             GL11.glTexCoord2f( maxX, maxY); GL11.glVertex2f( iX + fWidth, iY + fHeight ); //  invert these 2 lines
             GL11.glTexCoord2f( maxX, minY); GL11.glVertex2f( iX + fWidth, iY ); // for proper CCW vertexes
        GL11.glEnd();

Keeps doing the same thing.. Also when i render that fbo to another fbo, render good.

Fbo Class
Code: [Select]
public class RendererFrameBuffer
{
      /**
       * Fbo Texture
       **/
      private Texture pkTexture;
      /**
       * Fbo Viewport.
       **/
      private int iViewPortX;
      private int iViewPortY;
      /**
       * Render Index
       **/
      private int iRenderBuffer;
      /**
       * Frame Index
       **/
      private int iFrameBuffer;
      /**
       * Scratch buffer for texture ID's
       */
      private IntBuffer textureIDBuffer = BufferUtils.createIntBuffer( 1 );

    /**
     * Constructor
     *
     * @param texture
     */
    public RendererFrameBuffer( Texture texture, int iViewPortX, int iViewPortY )
    {
        this.iViewPortX = iViewPortX;
        this.iViewPortY = iViewPortY;
        pkTexture = texture;
        CreateFrameBuffer( );
    }

    /**
     * Constructor
     *
     * @param width
     * @param height
     */
    public RendererFrameBuffer( int iWidth, int iHeight, int iViewPortX, int iViewPortY )
    {
        this( TextureManager.CreateNullTexture(iWidth, iHeight), iViewPortX, iViewPortY );
    }

    /**
     * Create the FBO (Frame Buffer Object)
     */
    private void CreateFrameBuffer( )
    {
        // create the int buffer for extraction
        IntBuffer textureID = BufferUtils.createIntBuffer( 1 );
        // create the frameObjectID
        EXTFramebufferObject.glGenFramebuffersEXT(textureID);
        iFrameBuffer = textureID.get( 0 );
        // create the render buffer ID
        EXTFramebufferObject.glGenRenderbuffersEXT(textureID);
        iRenderBuffer = textureID.get( 0 );
        // Generate the FrameBuffer Texture
        try {
            // Firt bind the frameBuffer
            BindFrameBuffer( iFrameBuffer );
            // create The texture Buffer
            EXTFramebufferObject.glFramebufferTexture2DEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT,
                                                           EXTFramebufferObject.GL_COLOR_ATTACHMENT0_EXT,
                                                           GL11.GL_TEXTURE_2D,
                                                           pkTexture.GetID( ),
                                                           0 );
            // Second bind the render buffer
            BindRenderBuffer( iFrameBuffer );
            // initialize depth renderBuffer
            EXTFramebufferObject.glRenderbufferStorageEXT(EXTFramebufferObject.GL_RENDERBUFFER_EXT,
                                                          GL14.GL_DEPTH_COMPONENT24,
                                                          pkTexture.GetTextureWidth( ),
                                                          pkTexture.GetTextureHeight( ));
            // initialize frame renderBuffer
            EXTFramebufferObject.glFramebufferRenderbufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT,
                                                              EXTFramebufferObject.GL_DEPTH_ATTACHMENT_EXT,
                                                              EXTFramebufferObject.GL_RENDERBUFFER_EXT,
                                                              iRenderBuffer);
            // check for any error
            CheckErrorFrameBuffer( iFrameBuffer );
            // release the frameBuffer
            BindFrameBuffer( 0 );
        } catch ( Exception ex )
        {
            System.out.println("An error ocurred when try to create a RendererFrameBuffer");
        }
    }

    /**
     * Start the rendering into the
     * frame buffer
     */
    public void Enable( )
    {
        // save the atributes of the client
        GL11.glPushAttrib(GL11.GL_VIEWPORT_BIT);
        // Set the Buffer Context property
        GL11.glViewport( 0, 0, iViewPortX, iViewPortY );
        GL11.glClearColor( 0.0f, 0.0f, 0.0f, 0.0f);
        GL11.glClear( GL11.GL_COLOR_BUFFER_BIT );
        GL11.glLoadIdentity( );
        // bind the frameBuffer
        BindFrameBuffer( iFrameBuffer );

    }

    /**
     * Stop using the frameBuffer
     */
    public void Update( )
    {
        // Flush to the screen
        GL11.glFlush( );
        // unbind the frameBuffer
        BindFrameBuffer( 0 );
        // restore the atributes
        GL11.glPopAttrib( );
    }

    /**
     * @return The buffer texture
     */
    public Texture GetTexture( )
    {
        return pkTexture;
    }

    /**
     * Bind the frameID like the current frameBuffer
     * if's 0, then unbind it
     *
     * @param frameID
     */
    private final void BindFrameBuffer( int frameID )
    {
        EXTFramebufferObject.glBindFramebufferEXT( EXTFramebufferObject.GL_FRAMEBUFFER_EXT, frameID );
    }

    /**
     * Bind the renderID like the current renderBuffer
     * if's 0, then unbind it
     *
     * @param renderID
     */
    private final void BindRenderBuffer( int renderID )
    {
        EXTFramebufferObject.glBindRenderbufferEXT( EXTFramebufferObject.GL_RENDERBUFFER_EXT, renderID);
    }

    /**
     * Check if the framebuffer has an
     * error on creation
     *
     * @param frameID
     */
    private final void CheckErrorFrameBuffer( int frameID  )
    {
        // get the frameBufferError
        int frameBuffer = EXTFramebufferObject.glCheckFramebufferStatusEXT( EXTFramebufferObject.GL_FRAMEBUFFER_EXT );
        // print the error
        switch( frameBuffer )
        {
            case EXTFramebufferObject.GL_FRAMEBUFFER_COMPLETE_EXT:
                break;
            case EXTFramebufferObject.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
                System.out.println( "FrameBuffer: " + frameID
+ ", has caused a GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT exception" );
            case EXTFramebufferObject.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
                System.out.println( "FrameBuffer: " + frameID
+ ", has caused a GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT exception" );
            case EXTFramebufferObject.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
                System.out.println( "FrameBuffer: " + frameID
+ ", has caused a GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT exception" );
            case EXTFramebufferObject.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
                System.out.println( "FrameBuffer: " + frameID
+ ", has caused a GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT exception" );
            case EXTFramebufferObject.GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
                System.out.println( "FrameBuffer: " + frameID
+ ", has caused a GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT exception" );
            case EXTFramebufferObject.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
                System.out.println( "FrameBuffer: " + frameID
+ ", has caused a GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT exception" );
            default:
                System.out.println( "Unexpected reply from glCheckFramebufferStatusEXT: " + frameID);
        }
    }

    /**
     * This is a helper function, that
     * check if the FrameBufferObject
     * are supported
     *
     * @return
     */
    public final static boolean isSupported( )
    {
        return GLContext.getCapabilities().GL_EXT_framebuffer_object;
    }
Title: Re: [Help]: FBO Issues.
Post by: Fool Running on November 30, 2009, 18:05:20
Is it 90 degrees off, or is it upside-down?
Title: Re: [Help]: FBO Issues.
Post by: Wolftein on December 01, 2009, 20:25:51
Is it 90 degrees off, or is it upside-down?

is upside-down.
Title: Re: [Help]: FBO Issues.
Post by: Fool Running on December 03, 2009, 18:17:22
OpenGL puts (0,0) of a texture at the bottom-left instead of the top-left. My guess is that when you load your normal textures you are flipping the image so that it looks right. However, when you render to a texture, this flip is not done. That is probably what is causing your problem.
Title: Re: [Help]: FBO Issues.
Post by: Wolftein on December 14, 2009, 21:52:28
Fixed!

Code: [Select]
   /**
     * Start the rendering into the
     * frame buffer
     */
    public void Enable() {
        // save the atributes of the client
        GL11.glPushAttrib(GL11.GL_VIEWPORT_BIT);
        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glPushMatrix();
        // bind the frameBuffer
        BindFrameBuffer(iFrameBuffer);
        // Set the Buffer Context property
        GL11.glViewport(0, 0, iViewPortX, iViewPortY);
        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glLoadIdentity();
        GL11.glOrtho(0, iViewPortX, 0, iViewPortY, 1, -1);
        GL11.glMatrixMode(GL11.GL_MODELVIEW);
        GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
        GL11.glLoadIdentity();

    }

    /**
     * Stop using the frameBuffer
     */
    public void Update() {
        // Flush to the screen
        //GL11.glFlush();
        // unbind the frameBuffer
        BindFrameBuffer(0);
        // restore the atributes
        GL11.glPopAttrib();
        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glPopMatrix();
        GL11.glMatrixMode(GL11.GL_MODELVIEW);
    }

The problem was that in normal mode rendering from (0,0) starting from the top to (Width,Height)
Code: [Select]
GL11.glOrtho(0, iViewPortX, iViewPortY, 0, 1, -1);And the correct FBO Rendering is
Code: [Select]
GL11.glOrtho(0, iViewPortX, 0, iViewPortY, 1, -1);
Rendering to fbo we have to flip the orthogonal. is this a bug or fbo work this way?
Title: Re: [Help]: FBO Issues.
Post by: Fool Running on December 15, 2009, 13:51:48
Did you read my comment above? :P
OpenGL's default behavior is to have the origin (0, 0) at the bottom-left instead of the top-left (for textures, view, etc.). Usually its handled by setting the texture coordinates so that (0.0, 0.0) is at the bottom-left part of the polygon instead of the top-left, although you can also handle it the way you are currently doing it (by changing the parameters to glOrtho() ).