zoukankan      html  css  js  c++  java
  • OpenGL-非实时渲染与实时混合使用(有图有真相)

     视频教程请关注 http://edu.csdn.net/lecturer/lecturer_detail?lecturer_id=440

    一个朋友在问(我也曾经遇到过这样的事情),尤其是在地理信息上面,地图上的一些矢量数据,以及

    影像数据,在地图没有变化(比如,缩放,平移,编辑)都是不需要绘制的,只有需要绘制的时候,在去绘制

    背景,想必,这个道理大家一定都很明白,但是OpenGL每次在绘制的时候是必须都要进入渲染管线进行绘制

    于是很多人就在想,是否可以把一些不需要变化的数据绘制到图片上,需要绘制的时候在进行重新绘制,就像

    windows DC一样呢?在OpenGL早期的版本中是没有把数据绘制到图片上这个功能的,当然在创建OpenGL

    的时候有这个选项,本人亲身试验过,那个效率,那个差呀,OpenGL初始化代码如下所示:

    PIXELFORMATDESCRIPTOR pfd = 
            {
                sizeof(PIXELFORMATDESCRIPTOR), 
                1, 
                PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_SUPPORT_DIRECTDRAW | PFD_SWAP_EXCHANGE,
                PFD_TYPE_RGBA, 
                32, 
                8, 
                0,
                8,
                8,
                8,
                0,
                0, 
                0,
                32, 
                8,
                8,
                8, 
                8,
                24,
                8, 
                0, 
                PFD_MAIN_PLANE, 
                0,
                0, 
                0,
                0
            };

    红色的部分就是绘制到图片的选项。

      这种方案是不可取的,且不说他的效率问题,也满足不了目前的需求,在OpenGL1.1版本中,我们可以操作颜色缓冲区,或者

    叫帧缓冲区,在OpenGL中,至少存在两个缓冲区(当我们选择双缓冲绘制的时候),我们可以把数据绘制到缓冲区以后,在将

    缓冲区的数据直接的生成到纹理上,这样在把纹理绘制到背景中,这样,就可以有选择的去更新背景,而不是实时的去绘制背景

    数据,流程如下图所示:

    代码如下所示:

            glClearColor(1, 1, 1, 1);
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
            glPushAttrib(GL_COLOR_BUFFER_BIT | GL_PIXEL_MODE_BIT); // for GL_DRAW_BUFFER and GL_READ_BUFFER
            glDrawBuffer(GL_BACK);
            glReadBuffer(GL_BACK);
    
            //! 绘制数据到GL_BACK缓冲区
            //! 绘制完成,将缓冲区内容cpopy到纹理
    
            glBindTexture(GL_TEXTURE_2D, textureId);
            glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT);
            glBindTexture(GL_TEXTURE_2D, 0);
            glPopAttrib(); // GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT
    
            //! 其他实时绘制内容

    当然,这个方式比较老土,但能实现我们想要的功能,而且效率也不赖。在新的OpenGL版本中实现这个过程有很多方式

    例如比较流行的就是FBO( Fram buffer object),帧缓冲区对象,其实就是我们上面的过程,所不同的是:上面我们用到

    的缓冲区是OpenGL给我们创建的,我们没有办法干预创建的过程,而后者则可以干预这个过程,我们可以自己去创建帧

    缓冲区,并使用它,当然这个需要更高的OpenGL版本,你需要做更多的事情。

    下面是创建Frame Buffer Object 的代码:

            glGenFramebuffersEXT(1, &targetId._FBOID);
            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, targetId._FBOID);
    
            glGenRenderbuffersEXT(1, &targetId._RBOID);
            glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, targetId._RBOID);
            glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height);
            glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
    
            //glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, textureId, 0);
    
            glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, targetId._RBOID);
    
            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

    创建了以后,为了把数据绘制到上面,我们还需要给他绑定一个纹理,这个过程就像我们创建一个内存DC一样,如果没有和图片绑定

    绘制是没有任何意义的;

    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, targetId._FBOID);
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, textureId._texture, 0);

    绑定纹理以后,以后的绘制,则是将数据绘制到纹理上了;代码中可以这样使用:

    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, targetId->_FBOID);
    glBegin()
    ...
    glEnd()
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

    在一种方式就是PBuffer:像素缓冲区,过程和这个相似。每一种方式都有自己的优点与缺点,在不同的场合用不同的方式

    做到最大化利用就对了。

    后续会专门对离屏渲染做专门的例程。感谢大家阅读,本人能力有限,错误,误导之处请指教。

  • 相关阅读:
    【SAS NOTE】OUTPUT
    【SAS NOTES】_NULL_
    【SAS NOTE】sas 9.2 安装
    【SAS NOTE】FREQ
    纯数学教程 Page 203 例XLI (1)
    纯数学教程 Page 203 例XLI (3)
    纯数学教程 Page 203 例XLI (2)
    Prove Cauchy's inequality by induction
    纯数学教程 Page 325 例LXVIII (15) 调和级数发散
    纯数学教程 Page 325 例LXVIII (15) 调和级数发散
  • 原文地址:https://www.cnblogs.com/zhanglitong/p/3241938.html
Copyright © 2011-2022 走看看