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
对于深度缓存:使用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);
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区别:
(Same if you don't care about the values in the color-buffer (perhaps you only need depth values))
(faster and easier than using a texture)