opengles之VBO和FBO的结合使用

来源:互联网 发布:mysql不能输入中文 编辑:程序博客网 时间:2024/05/14 19:21

FBO的理论详见:http://blog.csdn.net/xiajun07061225/article/details/7283929/


FBO的创建:


class   FrameBufferId{public:FrameBufferId(){_width = 0;_height = 0;_FBOID = 0;_DEPTHID = 0;}public:unsigned    _width;unsigned    _height;unsigned    _FBOID;unsigned    _DEPTHID;public:/***   创建一个缓冲区对象*/void    create(int width, int height){_width = width;_height = height;//创建一个帧缓冲对象 第一个参数表示要创建的帧缓存的数目//第二个参数是保存创建的FBO的IDglGenFramebuffers(1, &_FBOID);//绑定glBindFramebuffer(GL_FRAMEBUFFER, _FBOID);//创建一个深度缓存glGenRenderbuffers(1, &_DEPTHID);//绑定glBindRenderbuffer(GL_RENDERBUFFER, _DEPTHID);//分配指定的内存空间:分配一个_width*_height的深度缓冲区 第二个参数为GL_DEPTH_COMPONENT16,是//指定我们的空间用来保存深度值,除此之外还可以保存GL_RGB/GL_RFBA或者模板缓存的信息,具体见定义//第一个参数必须是GL_RENDERBUFFER 第二个参数是可以渲染的颜色格式,可渲染的深度格式,或者可渲染的模板格式//第三个和第四个是以像素为单位指定数据所要占用内存的大小glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, _width, _height);//把深度缓存与FBO对象绑定在一起glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _DEPTHID);//解除绑定glBindFramebuffer(GL_FRAMEBUFFER, 0);}/***   使用对象*/void    begin(unsigned texId){glBindFramebuffer(GL_FRAMEBUFFER, _FBOID);//把2D纹理图像关联到FBO   第一个参数必须是GL_FRAMEBUFFER 第二个参数是关联纹理图像的关联点//第三个参数一般都是GL_TEXTURE_2D,第四个参数是纹理对象的ID号,最后一个参数是要被关联的纹理的mipmap等级glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texId, 0);}/***   使用完,回复状态*/void    end(){glBindFramebuffer(GL_FRAMEBUFFER, 0);}};

FBO的完整使用案例

#pragma once#include "CELLWinApp.hpp"//顶点结构体struct Vertex{float x, y, z;//顶点位置信息float u, v;//顶点纹理纹理坐标float r, g, b, a;//顶点颜色信息};//6个面共12个三角形Vertex g_cubeVertices[] ={// 第一个三角形{ -1.0f, -1.0f, 1.0f, 0, 1, 1.0f, 1.0f, 1.0f, 1.0f },{ 1.0f, -1.0f, 1.0f, 1, 1, 1.0f, 1.0f, 1.0f, 1.0f },{ 1.0f, 1.0f, 1.0f, 1, 0, 1.0f, 1.0f, 1.0f, 1.0f },{ -1.0f, -1.0f, 1.0f, 0, 1, 1.0f, 1.0f, 1.0f, 1.0f },{ 1.0f, 1.0f, 1.0f, 1, 0, 1.0f, 1.0f, 1.0f, 1.0f },{ -1.0f, 1.0f, 1.0f, 0, 0, 1.0f, 1.0f, 1.0f, 1.0f },//{ -1.0f, -1.0f, -1.0f, 0, 1, 1.0f, 0.0f, 0.0f, 1.0f },{ -1.0f, 1.0f, -1.0f, 1, 1, 1.0f, 0.0f, 0.0f, 1.0f },{ 1.0f, 1.0f, -1.0f, 1, 0, 1.0f, 0.0f, 0.0f, 1.0f },{ -1.0f, -1.0f, -1.0f, 0, 1, 1.0f, 0.0f, 0.0f, 1.0f },{ 1.0f, 1.0f, -1.0f, 1, 0, 1.0f, 0.0f, 0.0f, 1.0f },{ 1.0f, -1.0f, -1.0f, 0, 0, 1.0f, 0.0f, 0.0f, 1.0f },//{ -1.0f, 1.0f, -1.0f, 0, 1, 0.0f, 1.0f, 0.0f, 1.0f },{ -1.0f, 1.0f, 1.0f, 1, 1, 0.0f, 1.0f, 0.0f, 1.0f },{ 1.0f, 1.0f, 1.0f, 1, 0, 0.0f, 1.0f, 0.0f, 1.0f },{ -1.0f, 1.0f, -1.0f, 0, 1, 0.0f, 1.0f, 0.0f, 1.0f },{ 1.0f, 1.0f, 1.0f, 1, 0, 0.0f, 1.0f, 0.0f, 1.0f },{ 1.0f, 1.0f, -1.0f, 0, 0, 0.0f, 1.0f, 0.0f, 1.0f },//{ -1.0f, -1.0f, -1.0f, 0, 1, 0.0f, 1.0f, 0.0f, 1.0f },{ 1.0f, -1.0f, -1.0f, 1, 1, 0.0f, 1.0f, 0.0f, 1.0f },{ 1.0f, -1.0f, 1.0f, 1, 0, 0.0f, 1.0f, 0.0f, 1.0f },{ -1.0f, -1.0f, -1.0f, 0, 1, 0.0f, 1.0f, 0.0f, 1.0f },{ 1.0f, -1.0f, 1.0f, 1, 0, 0.0f, 1.0f, 0.0f, 1.0f },{ -1.0f, -1.0f, 1.0f, 0, 0, 0.0f, 1.0f, 0.0f, 1.0f },// Quad 4{ 1.0f, -1.0f, -1.0f, 0, 1, 0.0f, 0.0f, 1.0f, 1.0f },{ 1.0f, 1.0f, -1.0f, 1, 1, 0.0f, 0.0f, 1.0f, 1.0f },{ 1.0f, 1.0f, 1.0f, 1, 0, 0.0f, 0.0f, 1.0f, 1.0f },{ 1.0f, -1.0f, -1.0f, 0, 1, 0.0f, 0.0f, 1.0f, 1.0f },{ 1.0f, 1.0f, 1.0f, 1, 0, 0.0f, 0.0f, 1.0f, 1.0f },{ 1.0f, -1.0f, 1.0f, 0, 0, 0.0f, 0.0f, 1.0f, 1.0f },//{ -1.0f, -1.0f, -1.0f, 0, 1, 0.0f, 0.0f, 1.0f, 1.0f },{ -1.0f, -1.0f, 1.0f, 1, 1, 0.0f, 0.0f, 1.0f, 1.0f },{ -1.0f, 1.0f, 1.0f, 1, 0, 0.0f, 0.0f, 1.0f, 1.0f },{ -1.0f, -1.0f, -1.0f, 0, 1, 0.0f, 0.0f, 1.0f, 1.0f },{ -1.0f, 1.0f, 1.0f, 1, 0, 0.0f, 0.0f, 1.0f, 1.0f },{ -1.0f, 1.0f, -1.0f, 0, 0, 0.0f, 0.0f, 1.0f, 1.0f }};class   FrameBufferId{public:FrameBufferId(){_width = 0;_height = 0;_FBOID = 0;_DEPTHID = 0;}public:unsigned    _width;unsigned    _height;unsigned    _FBOID;unsigned    _DEPTHID;public:/***   创建一个缓冲区对象*/void    create(int width, int height){_width = width;_height = height;//创建一个帧缓冲对象 第一个参数表示要创建的帧缓存的数目//第二个参数是保存创建的FBO的IDglGenFramebuffers(1, &_FBOID);//绑定glBindFramebuffer(GL_FRAMEBUFFER, _FBOID);//创建一个深度缓存glGenRenderbuffers(1, &_DEPTHID);//绑定glBindRenderbuffer(GL_RENDERBUFFER, _DEPTHID);//分配指定的内存空间:分配一个_width*_height的深度缓冲区 第二个参数为GL_DEPTH_COMPONENT16,是//指定我们的空间用来保存深度值,除此之外还可以保存GL_RGB/GL_RFBA或者模板缓存的信息,具体见定义//第一个参数必须是GL_RENDERBUFFER 第二个参数是可以渲染的颜色格式,可渲染的深度格式,或者可渲染的模板格式//第三个和第四个是以像素为单位指定数据所要占用内存的大小glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, _width, _height);//把深度缓存与FBO对象绑定在一起glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _DEPTHID);//解除绑定glBindFramebuffer(GL_FRAMEBUFFER, 0);}/***   使用对象*/void    begin(unsigned texId){glBindFramebuffer(GL_FRAMEBUFFER, _FBOID);//把2D纹理图像关联到FBO   第一个参数必须是GL_FRAMEBUFFER 第二个参数是关联纹理图像的关联点//第三个参数一般都是GL_TEXTURE_2D,第四个参数是纹理对象的ID号,最后一个参数是要被关联的纹理的mipmap等级glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texId, 0);}/***   使用完,回复状态*/void    end(){glBindFramebuffer(GL_FRAMEBUFFER, 0);}};class   OffscreenApp :public CELLWinApp{public:PROGRAM_P2_T2_C3    _shader;unsigned            _textureId;//! 顶点缓冲区unsigned            _vertexId;//! 创建一个FBO FameBufferObject对象FrameBufferId       _fbo;//! 纹理对象unsigned            _dynamicTexture;public:OffscreenApp(){_textureId = -1;}public:/***   创建一个文理函数*/unsigned    createTexture(int width, int height, unsigned inteFmt, unsigned dataFmt, void* data){unsigned    texId = 0;/***   产生一个纹理Id,可以认为是纹理句柄,后面的操作将书用这个纹理id*/glGenTextures(1, &texId);/***   使用这个纹理id,或者叫绑定(关联)*/glBindTexture(GL_TEXTURE_2D, texId);/***   指定纹理的放大,缩小滤波,使用线性方式,即当图片放大的时候插值方式*/glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);/***   将图片的rgb数据上传给opengl.*/glTexImage2D(GL_TEXTURE_2D,      //! 指定是二维图片0,                  //! 指定为第一级别,纹理可以做mipmap,即lod,离近的就采用级别大的,远则使用较小的纹理inteFmt,            //! 纹理的使用的存储格式width,              //! 宽度,老一点的显卡,不支持不规则的纹理,即宽度和高度不是2^n。height,             //! 宽度,老一点的显卡,不支持不规则的纹理,即宽度和高度不是2^n。0,                  //! 是否的边dataFmt,            //! 数据的格式GL_UNSIGNED_BYTE,   //! 数据是8bit数据data);return  texId;}//! 重写初始化函数virtual void    onInit(){_shader.initialize();loadTexture();glEnable(GL_DEPTH_TEST);//! 创建顶点缓冲区glGenBuffers(1, &_vertexId);glBindBuffer(GL_ARRAY_BUFFER, _vertexId);//绑定//将顶点数据上传至显卡内存glBufferData(GL_ARRAY_BUFFER, sizeof(g_cubeVertices), g_cubeVertices, GL_STATIC_DRAW);//解除绑定glBindBuffer(GL_ARRAY_BUFFER, 0);//! 初始化FBO_fbo.create(_winWidth, _winHeight);_dynamicTexture = createTexture(_fbo._width, _fbo._height, GL_RGBA, GL_RGBA, 0);}virtual void    loadTexture(){//1 获取图片格式FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType("Debug/data/image/smoke.tga", 0);//2 加载图片FIBITMAP    *dib = FreeImage_Load(fifmt, "Debug/data/image/smoke.tga", 0);//3 转化为rgb 24色dib = FreeImage_ConvertTo24Bits(dib);//4 获取数据指针BYTE    *pixels = (BYTE*)FreeImage_GetBits(dib);int     width = FreeImage_GetWidth(dib);int     height = FreeImage_GetHeight(dib);_textureId = createTexture(width, height, GL_RGB, GL_RGB, pixels);/***   释放内存*/FreeImage_Unload(dib);}void    drawCube(int viewW, int viewH){static  float x = 0;glBindBuffer(GL_ARRAY_BUFFER, _vertexId);_shader.begin();{glUniform1i(_shader._texture, 0);CELL::matrix4   matProj = CELL::perspective(45.0f, float(viewW) / float(viewH), 0.1f, 100.0f);CELL::matrix4   model(1);model.translate(0.0f, 0.0f, -10.0f);CELL::matrix4   matRot(1);matRot.rotateYXZ(x, x, x);x += 1.0f;CELL::matrix4   mvp = matProj *  model * (matRot);glUniformMatrix4fv(_shader._MVP, 1, false, mvp.data());glVertexAttribPointer(_shader._positionAttr, 3, GL_FLOAT, false, sizeof(Vertex), 0);glVertexAttribPointer(_shader._uvAttr, 2, GL_FLOAT, false, sizeof(Vertex), (void*)12);glVertexAttribPointer(_shader._colorAttr, 4, GL_FLOAT, false, sizeof(Vertex), (void*)20);glDrawArrays(GL_TRIANGLES, 0, sizeof(g_cubeVertices) / sizeof(g_cubeVertices[0]));}_shader.end();glBindBuffer(GL_ARRAY_BUFFER, 0);}virtual void    render(){_fbo.begin(_dynamicTexture);{glClearColor(1, 1, 1, 1);glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);glViewport(0, 0, _fbo._width, _fbo._height);glBindTexture(GL_TEXTURE_2D, _textureId);drawCube(_fbo._width, _fbo._height);}_fbo.end();glClearColor(0, 0, 0, 1);glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);glViewport(0, 0, _winWidth, _winHeight);//glBindTexture(GL_TEXTURE_2D,_textureId);glBindTexture(GL_TEXTURE_2D, _dynamicTexture);//! 绘制到窗口上drawCube(_winWidth, _winHeight);eglSwapBuffers(_display, _surface);}};

// 完整案例下载地址:http://download.csdn.net/detail/hb707934728/9844615