opengles之VBO和FBO的结合使用

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的ID
		glGenFramebuffers(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的ID
		glGenFramebuffers(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


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值