Render OpenGL scene to texture using FBO in fixed function pipeline drawing

前端 未结 1 1631
攒了一身酷
攒了一身酷 2020-12-02 03:06

The Problem

I work on the open source game torcs (http://torcs.sourceforge.net/). The game\'s graphic pipeline is still using the fixed function pipeline (FFP) of

相关标签:
1条回答
  • 2020-12-02 03:51

    When I compared your code with mine working engine I see these differences so try them one by one:

    1. texture format

      you are using:

      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, screen_width, screen_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
      

      so merging all your to:

      GL_COLOR_ATTACHMENT0: GL_RGBA,GL_RGBA,GL_UNSIGNED_BYTE
      GL_COLOR_ATTACHMENT1: GL_RGBA,GL_RGBA,GL_UNSIGNED_BYTE
      

      I am using:

      GL_COLOR_ATTACHMENT0 : GL_RGBA           , GL_RGBA8            , GL_UNSIGNED_BYTE
      GL_DEPTH_ATTACHMENT  : GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT16, GL_UNSIGNED_BYTE
      GL_STENCIL_ATTACHMENT: GL_STENCIL_INDEX  , GL_STENCIL_INDEX8   , GL_UNSIGNED_BYTE
      

      You need to change internal pixel format of textures to specify bit width. If my memory serves well when I code this (some years back) it did not work with just GL_RGBA,GL_RGBA.

    2. depth target

      I am using depth and stencil textures the same way as color attachment I do not use any RenderBuffer calls. That does not mean your code is wrong but mine is tested and works.

    3. texture size

      This is most likely not valid anymore as most gfx cards support rectangle texture extension but OpenGL textures should be power of 2 resolution. So for starters try 512x512 instead of your 640x480 And change back when your code is working (just to be sure ...).

    In case it helps here is my C++ FBO class taken from mine engine so you got something to compare to (will not work alone as it uses textures and stuff from the engine):

    //------------------------------------------------------------------------------
    //--- Open GL FBO object ver 2.31 ----------------------------------------------
    //------------------------------------------------------------------------------
    #ifndef _OpenGL_FBO_h
    #define _OpenGL_FBO_h
    //------------------------------------------------------------------------------
    class OpenGL_FBO
        {
    public:
        GLuint fbo;
        int xs,ys;
        struct _dst
            {
            GLint txr;      // texture id
            GLenum dst;     // GL_DEPTH_COMPONENT, GL_COLOR_ATTACHMENT0, ...
            _dst()          { txr=-1; dst=GL_COLOR_ATTACHMENT0; }
            _dst(_dst& a)   { *this=a; }
            ~_dst()         {}
            _dst* operator = (const _dst *a) { *this=*a; return this; }
            //_dst* operator = (const _dst &a) { ...copy... return this; }
            };
        List<_dst> dst;
    
        OpenGL_FBO() { fbo=0xFFFFFFFF; xs=1; ys=1; dst.reset(); }
        OpenGL_FBO(OpenGL_FBO& a)   { fbo=0xFFFFFFFF; dst.reset(); *this=a; }
        ~OpenGL_FBO() { if (fbo!=0xFFFFFFFF) glDeleteFramebuffers(1,&fbo); }
        OpenGL_FBO* operator = (const OpenGL_FBO *a) { *this=*a; return this; }
        //OpenGL_FBO* operator = (const OpenGL_FBO &a) { ...copy... return this; }
    
        void resize(OpenGLscreen &scr,int _xs=-1,int _ys=-1)
            {
            int i;
            _dst *d;
            if (_xs<=0) _xs=scr.xs;
            if (_ys<=0) _ys=scr.ys;
    //      for (xs=1;xs<_xs;xs<<=1);
    //      for (ys=1;ys<_ys;ys<<=1);
            xs=_xs; ys=_ys; // ****
    
            if (fbo==0xFFFFFFFF) glGenFramebuffers(1,&fbo);
            glBindFramebuffer(GL_FRAMEBUFFER,fbo);
            for (d=dst.dat,i=0;i<dst.num;i++,d++)
                {
                scr.txrs.bind(d->txr);
                scr.txrs.resize(d->txr,xs,ys,1);
    //          glFramebufferTexture2D(GL_FRAMEBUFFER,t->dst,GL_TEXTURE_2D,scr.txrs.names[d->txr],0);
                glFramebufferTexture(GL_FRAMEBUFFER,d->dst,scr.txrs.names[d->txr],0);
    //          glCheckFramebufferStatus(GL_FRAMEBUFFER);
                }
            scr.txrs.unbind();
            glBindFramebuffer(GL_FRAMEBUFFER,0);
            }
        int add(OpenGLscreen &scr,int _dest=GL_COLOR_ATTACHMENT0)   // add txr to fbo
            {
            _dst d;
            OpenGL_TXR tmp;
            // colro atachments
            tmp.pixelformat =GL_RGBA;
            tmp.pixeliformat=GL_RGBA8;
            tmp.pixeltype=GL_UNSIGNED_BYTE;
            tmp.mag=GL_NEAREST;
            tmp.min=GL_NEAREST;
            if (_dest==GL_DEPTH_ATTACHMENT)
                {
                tmp.pixelformat =GL_DEPTH_COMPONENT;
                tmp.pixeliformat=GL_DEPTH_COMPONENT16;
    //          tmp.pixeltype=GL_FLOAT;
                tmp.pixeltype=GL_UNSIGNED_BYTE;
                }
            if (_dest==GL_STENCIL_ATTACHMENT)
                {
                tmp.pixelformat =GL_STENCIL_INDEX;
                tmp.pixeliformat=GL_STENCIL_INDEX8;
                tmp.pixeltype=GL_UNSIGNED_BYTE;
                }
            tmp.xs=xs;
            tmp.ys=ys;
            tmp.zs=1;
            tmp._mipmap=0;
            tmp.txrtype=GL_TEXTURE_2D;
            d.txr=scr.txrs.add(tmp);
            d.dst=_dest;
            dst.add(d);
            return d.txr;
            }
        void bind(OpenGLscreen &scr)    // init fbo >> txr
            {
            // init and resize
            if (fbo==0xFFFFFFFF) glGenFramebuffers(1,&fbo);
            glBindFramebuffer(GL_FRAMEBUFFER,fbo);
            glViewport(0,0,xs,ys);
            scr.cls();
            }
        void unbind(OpenGLscreen &scr)
            {
            glBindFramebuffer(GL_FRAMEBUFFER,0);
            glViewport(scr.x0,scr.y0,scr.xs,scr.ys);
            }
        };
    //------------------------------------------------------------------------------
    #endif
    //------------------------------------------------------------------------------
    //--- end. ---------------------------------------------------------------------
    //------------------------------------------------------------------------------
    

    where:


    OpenGLscreen scr is my rendering engine
    scr.cls() is just glClear and stuff to init frame
    scr.x0,y0,xs,ys is viewport of target window
    scr.txrs is texture system class (handles all the textures) like add new texture loading/saving from/to file, conversion between CPU/GPU and much much more.

    I also use mine dynamic list template so:


    List<double> xxx; is the same as double xxx[];
    xxx.add(5); adds 5 to end of the list
    xxx[7] access array element (safe)
    xxx.dat[7] access array element (unsafe but fast direct access)
    xxx.num is the actual used size of the array
    xxx.reset() clears the array and set xxx.num=0
    xxx.allocate(100) preallocate space for 100 items

    typical usage is:

    // [globals and init]
    OpenGLScreen scr; // can ignore this
    OpenGL_FBO fbo;
    scr.init(window_handle); // init OpenGL stuff can ignore this
    fbo.add(scr,GL_COLOR_ATTACHMENT0);
    fbo.add(scr,GL_DEPTH_ATTACHMENT);
    fbo.resize(scr,512,512);
    
    // [render loop]
    fbo.bind(scr);
    // here render
    fbo.unbind(scr);
    // here you can use the textures fbo.dst[].txr
    

    Take a look here for specific example:

    • Render filled complex polygons with large number of vertices with OpenGL

    Of coarse for those of you that are stuck with older Intel HD graphics do not expect that this will work due to bug in drivers. See this slow workaround:

    • OpenGL Scale Single Pixel Line
    0 讨论(0)
提交回复
热议问题