zoukankan      html  css  js  c++  java
  • 关于FBO(FrameBuffer Object)的一些理解

      先来整理下本人对FBO的理解。FBO是FrameBuffer Object的首字母简称。翻译过来就是帧缓冲区的意思。根据我的理解,OpenGL作为图形API,可以看做是画笔,帧缓冲区可以比作画布。我们使用OpenGL在帧缓冲区上“作画”(渲染)。

      首先,我们需要建立OpenGL Context,即获得一套“作画”的工具。以Win32 OpenGL为例,我们需要如下流程去建立一个标准的OpenGL Context:

      1、创建一个窗口类(WNDCLASS/WNDCLASSEX)。

      2、注册窗口类(RegisterClass)。

      3、调用CreateWindow/CreateWindowEx创建新窗口,返回窗口句柄 HWND。

      4、创建设备描述符PIXELFORMATDESCRIPTOR pfd。该结构体中包含即将要创建的OpenGL context的各种信息,包括是否支持双缓冲区、像素位数、Z-buffer位数等各种缓冲区位宽。

      5、获取新生成窗口的Device Context句柄HDC hDC,通过调用GetDC(HWND)获得。

      6、调用ChoosePixelFormat(hDC,&pfd)选择合适的像素格式,如果成功,返回像素格式的索引GLuint nPixelFormat。

      7、利用上一步的结果调用SetPixelFormat(hDC,nPixelFormat,&pfd),设置像素格式。

      8、调用wglCreateContext(hDC)获得 OpenGL Context 句柄 HGLRC hRC;

      9、设置上一步获得的OpenGL Context为当前的Context,通过调用wglMakeCurrent(hDC,hRC);

      不总结不知道,一总结发现一步一步下来,步骤还是挺多的。要注意的一点是,上述9步中大部分函数调用是为了生成/申请相关窗口或者句柄,为了提高程序的鲁棒性,需要及时检查返回值的有效性。

      注意:在上述第4步中,我们在设备描述符中通过参数设置了各个缓冲区的位宽。位宽为0当然就是没有这个缓冲区的意思啦。


      在建立了OpenGL渲染环境之后,相当于获得了一只画笔,而此时我们有一块默认的画布,即我们的屏幕,default framebuffer。我们渲染的目的地就是我们的屏幕,我们画出来的东西,会显示在屏幕上。这个default framebuffer 是与一系列缓冲区相关联的(具体有哪些缓冲区,多少位的缓冲区,是建立OpenGL Context的时候用户自定义的。一般来讲,必要的是颜色缓冲区,深度缓冲区。模板缓冲区、累加缓冲区这俩哥们儿可选。)。我们需要颜色缓冲区来存储我们渲染物体的颜色,需要深度缓冲区来进行深度测试,等等。具体的渲染过程是如何进行的,就是OpenGL Render Pipeline的东西了。在此不细表。

      之后随着新需求的出现和OpenGL的发展,off-screen render技术出现了,即离屏渲染(离线渲染)。我去,off-screen render,离线渲染,乍一听好牛逼的样子,其实很简单。我们把物体直接渲染到屏幕上,就是“在线渲染”。同理,我们把物体渲染到别的地方,不渲染到屏幕上,那不就是“离线渲染”了么。 那我们不渲染到屏幕,渲染到哪儿去呢?

      OpenGL 从某版本之后,引入了Framebuffer Object。 XXXX Object,我们见过很多了,像Vertex Buffer Object, Vertex Array Object。这次的Framebuffer Object是什么东西呢?

      根据本人的理解,FBO(Framebuffer Object)就是OpenGL模拟default framebuffer的功能和结构创建的一种可以作为“画布”使用的Object。也就是说,你生成一个FBO,根据你的渲染需要,捯饬捯饬,然后把你想渲染的东西渲染到你刚生成的这个FBO里面,而不是直接渲染到屏幕上,就是这个样子。Default framebuffer 有很多支撑渲染行为的缓冲区,FBO也可以有,但是要你手动去生成、设置和绑定

      值得注意的是FBO的角色更像是一个管理者,管理着所有支撑渲染的RenderBuffers和Textures,OpenGL没有为FBO分配内存空间去存储渲染所需的几何、像素数据等。但是,FBO有很多Attachment Point,顾名思义,我们把真正起作用的、具有实际内存空间占用的Renderbuffer和Texutures依附在FBO上,FBO起到管理的作用。这点跟VAO有点类似,是一批量“状态”的集合。VAO的事情我觉得有必要再整理下思路,但是此处暂且按下不表。

      最近爱上了Viso作图,如下:

       

      

      貌似不能插pdf,只能插图片。不清晰,此处有pdf: https://files.cnblogs.com/chandler00x/FBO.pdf

      下面简单说下两种情况的用法:

      下面这段代码说明如何将Renderbuffer与FBO绑定。

     1 GLuint hFbo,hTex,hDepth,hColor;
     2 
     3     glGenFramebuffers(1,&hFbo);
     4     glBindFramebuffer(GL_FRAMEBUFFER,hFbo);
     5 
     6     glGenRenderbuffers(1,&hDepth);
     7     glBindRenderbuffer(GL_RENDERBUFFER,hDepth);
     8     
     9     //为当前的Renderbuffer分配空间,格式为GL_DEPTH_COMPONENT,顾名思义 
    10     //这个Renderbuffer肯定是与depth test相关的。
    11     glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT,m_width,m_height);
    12 
    13     //将当前的Renderbuffer与Framebuffer Object的GL_DEPTH_ATTACHMENT的连接点
    14     //连接起来。再顾名思义,肯定是与Depth test相关的。
    15     glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER,hDepth);
    16 
    17     glGenRenderbuffers(1,&hColor);
    18     glBindRenderbuffer(GL_RENDERBUFFER,hColor);
    19 
    20     //为当前的Renderbuffer分配空间,格式为GL_RGBA
    21     glRenderbufferStorage(GL_RENDERBUFFER,GL_RGBA,m_width,m_height);
    22 
    23     //与FBO的GL_COLOR_ATTACHMENT0连接起来。
    24     glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_RENDERBUFFER,hColor);
    25 
    26     //检查Framebuffer的完整性,十分必要!!!!!
    27     //十分必要!!!!!
    28     GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    29     if( status != GL_FRAMEBUFFER_COMPLETE)
    30         printf("Framebuffer incomplete!
    ");
    31     else
    32         printf("Framebuffer complete!
    ");

       下面这段代码说明如何将Texture与FBO绑定。

     

     1 GLuint hFbo,hTex,hDepth,hColor;
     2 
     3     glGenFramebuffers(1,&hFbo);
     4     glBindFramebuffer(GL_FRAMEBUFFER,hFbo);
     5 
     6     glGenRenderbuffers(1,&hDepth);
     7     glBindRenderbuffer(GL_RENDERBUFFER,hDepth);
     8     
     9     //为当前的Renderbuffer分配空间,格式为GL_DEPTH_COMPONENT,顾名思义 
    10     //这个Renderbuffer肯定是与depth test相关的。
    11     glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT,m_width,m_height);
    12 
    13     //将当前的Renderbuffer与Framebuffer Object的GL_DEPTH_ATTACHMENT的连接点
    14     //连接起来。再顾名思义,肯定是与Depth test相关的。
    15     glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER,hDepth);
    16 
    17     glActiveTexture(GL_TEXTURE0);
    18     glGenTextures(1,&hTex);
    19     glBindTexture(GL_TEXTURE_2D,hTex);
    20 
    21     //为纹理分配空间。
    22     glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,m_width,m_height,0,GL_RGBA,GL_UNSIGNED_BYTE,NULL);
    23 
    24     //与FBO的GL_COLOR_ATTACHMENT0绑定,Color。。color。。
    25     glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,hTex,0);
    26 
    27 
    28     //检查Framebuffer的完整性,十分必要!!!!!
    29     //十分必要!!!!!
    30     GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    31     if( status != GL_FRAMEBUFFER_COMPLETE)
    32         printf("Framebuffer incomplete!
    ");
    33     else
    34         printf("Framebuffer complete!
    ");

     

     

  • 相关阅读:
    正则匹配、替换
    C# 算法
    .Net Core 初体验及总结(内含命令大全)
    docker 开放 2375端口
    docker 中 mysql group by 报错
    微信小程序全局变量改变监听
    Linux 中 IDEA 不能调试(Debug)项目
    JavaMail发送邮件后再通过JavaMail接收格式问题
    Linux 安装 RabbitMQ
    SpringBoot 集成 Swagger
  • 原文地址:https://www.cnblogs.com/chandler00x/p/3886062.html
Copyright © 2011-2022 走看看