fbo多个color buffer绘制

http://www.cnblogs.com/cloudseawang/archive/2008/12/07/1349661.html

FBO: frame buffer object主要用来render-to-texture,进行off-screen rendering.

以下是使用步骤:

1,初始化glewInit(),然后检测 GPU是否支持GL_EXT_FRAMEBUFFER_OBJECT扩展

2,创建FBO ,

GLuint fbo, color;
// Create an FBO
glGenFramebuffersEXT(1, &fbo);
// Create color texture
glGenTextures(1, &color);
glBindTexture(GL_TEXTURE_2D, color);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, NULL);

glGenerateMipmapEXT(GL_TEXTURE_2D);//生成mipmap
// Bind the FBO and attach color texture to it
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, color, 0);

对于一个fbo,可以绑定多个GL_COLOR_ATTACHMENT(I)_EXT,即可以有多个color

查询当前设备颜色绑定点的最大值:

  1. <span style="font-family:Microsoft YaHei;font-size:14px;">GLuint maxbuffers;  
  2. glGetIntergeri(GL_MAX_COLOR_ATTACHMENTS, &maxbuffers);</span>  

对于深度缓存:使用32位float纹理

 Gluint depth,

  glGenTextures(1, &detph);

 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, depth);
  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH_COMPONENT32F_NV,
   widht, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);

 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_EXT,depth, 0);

 对于stencil buffer,目前是和depth buffer绑定在一起的,需要支持GL_EXT_PACKED_DEPTH_STENCIL extension扩展。

其定义方式如下:

 Gluint depthStencil;

glGenTextures(1, &detphStencil);

glBindTexture(GL_TEXTURE_2D, depthStencil);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8_EXT, widht, height, 0,
GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL);

glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_TEXTURE_2D, depthStencil,0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
GL_TEXTURE_2D, depthStencil,0);

对于depth, stencil buffer绑定的纹理,不支持mipmap.

另外也可以使用renderbuffer与fbo绑定。

 注意:fbo里如果不指定要写depth buffer,stencil buffer,仅仅enable depth test, 并不会写depth buffer!

3,使用fbo ,使用前一定要 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);

返回到主frambebuffer只需要

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

 

4,对于绑定多个color buffer,如果指定渲染到其中某一个buffer,则用glDrawBuffer

// Render to color0
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glDrawBuffer(GL_ COLOR_ATTACHMENT0_EXT);
// Render to color1
glDrawBuffer(GL_ COLOR_ATTACHMENT1_EXT);

5, 如果一次渲染多个color buffer,则是Mulitple rendering target (MRT)。如果要指定渲染的起始buffer,则用glDrawBuffers

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glDrawBuffers(GL_ COLOR_ATTACHMENT(I)_EXT);

查询可以一次同时写入缓冲区的个数:

  1. <span style="font-family:Microsoft YaHei;font-size:14px;">GLuint maxbuffers;  
  2. glGetIntergeri(GL_MAX_DRAW_BUFFERS, &maxbuffers);</span>  

因而,如果我们已经把两个纹理分别绑定到绑定点0和1,现在我们想同时渲染输出到这两个纹理上,我们就可以按以下代码来写:

  
  
  1. <span style="font-family:Microsoft YaHei;font-size:14px;">GLenum buffers[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT };  
  2. glDrawBuffers(2, buffers);</span>  

当上面的函数正确运行之后,OpenGL 便建立了一个双颜色缓冲渲染输出的环境

6,读取fbo渲染的内容,有两种办法

定义输出图像:

  unsigned char output_image = new unsigned char[ width*height];

a,   直接读buffer, 

    glReadBuffer(GL_ COLOR_ATTACHMENT(I)_EXT)

     glReadPixels( 0,  0,width,height, GL_RGB,  GL_FLOAT,output_image);

b, 读绑定的texture ,color是绑定的纹理
  glBindTexture(GL_TEXTURE_RECTANGLE_ARB,color);
  glGetTexImage(GL_TEXTURE_RECTANGLE_ARB,0,GL_DEPTH_COMPONENT,GL_UNSIGNED_BYTE,output_image);

 7,delete FBO

glDeleteFramebuffersEXT(1,&fbo);

RBO和FBO To Texture区别:

  • when you want to make OpenGL do depth/stencil tests, but don't care about the actual values in the buffer, you will make a depth/stencil renderbuffer (no need to use textures if don't care about the values - and you can't for stencil). 
    (Same if you don't care about the values in the color-buffer (perhaps you only need depth values))
  • when you need to process the values of a buffer on the CPU (not the GPU) you should use a renderbuffer instead of a texture
    (faster and easier than using a texture)
  • if you want build-in AA on the color-buffer, you have no choice but to use a renderbuffer
在OpenGL中,你可以使用Framebuffer Objects (FBOs) 和 Framebuffer Attachments 来合并多个帧缓冲的内容。通常,这涉及到创建多个FBO,每个FBO都有一个颜色附件,然后将它们链接在一起。以下是一个基本的例子,展示了如何在C++中操作。 首先,确保包含了所需的头文件: ```cpp #include <GL/glut.h> #include <GL/glu.h> #include <GLFW/glfw3.h> #include <iostream> #include <string> #include <vector> // FBO管理类 class FrameBufferObject { private: GLuint fboID, depthAttachmentID; public: FrameBufferObject(size_t width, size_t height) : fboID(glGenFramebuffers(1)), depthAttachmentID(0) { glGenRenderbuffers(1, &depthAttachmentID); glBindFramebuffer(GL_FRAMEBUFFER, fboID); // 创建纹理和深度缓冲区 GLubyte* pixels[4] = {0}; glTexImage2D(GL_COLOR_ATTACHMENT0, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, 0); // 添加深度缓冲区 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthAttachmentID); // 检查配置是否成功 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { std::cerr << "Failed to create framebuffer!" << std::endl; glDeleteFramebuffers(1, &fboID); glDeleteRenderbuffers(1, &depthAttachmentID); } } ~FrameBufferObject() { glDeleteFramebuffers(1, &fboID); glDeleteRenderbuffers(1, &depthAttachmentID); } GLuint getFBO() const { return fboID; } }; ``` 接下来,你需要创建两个FBO,并将它们组合到一个大的FBO中: ```cpp void combineFrameBuffers(GLFWwindow* window, int w, int h) { FrameBufferObject fbo1(w / 2, h / 2); FrameBufferObject fbo2(w - w / 2, h - h / 2); // 清除屏幕 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 绑定第一个FBO glBindFramebuffer(GL_FRAMEBUFFER, fbo1.getFBO()); drawSceneInHalf(window, w / 2, h / 2); // 绘制左半部分到 fbo1 // 绑定第二个FBO glBindFramebuffer(GL_FRAMEBUFFER, fbo2.getFBO()); drawSceneInRight(window, w - w / 2, h - h / 2); // 绘制右半部分到 fbo2 // 现在将两个FBO连接起来 glBindFramebuffer(GL_FRAMEBUFFER, 0); // 主屏幕作为目标帧缓冲 glBlitFramebuffer(fbo1.getFBO(), 0, 0, w / 2, h / 2, 0, 0, w / 2, h / 2, GL_COLOR_BUFFER_BIT, GL_NEAREST); glBlitFramebuffer(fbo2.getFBO(), w / 2, h / 2, w, h, w / 2, 0, w, h / 2, GL_COLOR_BUFFER_BIT, GL_NEAREST); } // 假设drawSceneInHalf 和 drawSceneInRight 是绘制一半画面的函数 ``` 记得在合适的地方清理和销毁FBO,例如在窗口关闭时。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值