天天看点

OpenGLES---缓冲区

{
	1:顶点缓冲区 GL_ARRAY_BUFFER
	2:索引缓冲区 GL_ELEMENT_ARRAY_BUFFER
	3:帧缓冲区 GL_FRAMEBUFFER/GL_RENDERBUFFER
	4:封装
}
           
{1:顶点缓冲区 GL_ARRAY_BUFFER
	
	OpenGL-ES 中 Vertex Arrays/Buffer Objects 在这个阶段发生

	struct VX{
		float x, y, z;
		float u,v;
		float r, g, b,a;
	};

	float zOff=-2.1f;
	VX vertexs[] ={
		{ -1.0f,-1.0f, zOff,	0.0f,0.0f,	1.0f,1.0f, 1.0f,1.0f },
		{  1.0f,-1.0f, zOff,	1.0f,0.0f,	1.0f,1.0f, 1.0f,1.0f },
		{  1.0f, 1.0f, zOff,	1.0f,1.0f,	1.0f,1.0f, 1.0f,1.0f },

		{ -1.0f,-1.0f, zOff,	0.0f,0.0f,	1.0f,1.0f, 1.0f,1.0f },
		{  1.0f, 1.0f, zOff,	1.0f,1.0f,	1.0f,1.0f, 1.0f,1.0f },
		{ -1.0f, 1.0f, zOff,	0.0f,1.0f,	1.0f,1.0f, 1.0f,1.0f },
	};

	unsigned vbId; //数据id

	{创建数据
		glGenBuffers(1,&vbId);
		glBindBuffer(GL_ARRAY_BUFFER,vbId); //绑定/取消缓冲区
		glBufferData(GL_ARRAY_BUFFER,sizeof(vertexs),vertexs,GL_STATIC_DRAW);//设置缓冲区数据
		glBindBuffer(GL_ARRAY_BUFFER,0);//绑定/取消缓冲区
	}

	{使用数据
		glBindBuffer(GL_ARRAY_BUFFER,vbId);//绑定/取消缓冲区
		glVertexAttribPointer(shader._position,3,  GL_FLOAT,   false,  sizeof(VX),(void*)0);
		glVertexAttribPointer(shader._tpos,    2,  GL_FLOAT,   false,  sizeof(VX),(void*)(3*sizeof(float)));
		glVertexAttribPointer(shader._color,   4,  GL_FLOAT,   false,  sizeof(VX),(void*)(3*sizeof(float)+2*sizeof(float)));
		glDrawArrays(GL_TRIANGLES,0,6);//三角形 (三个点画一个三角形)
		glBindBuffer(GL_ARRAY_BUFFER,0);//绑定/取消缓冲区 注意:使用完就制空,OpenGL-ES是状态机
	}

	切记:缓冲数据在什么地方用在什么地方制空,不指空的话,下面的数据全是这个缓冲数据

	注意:
		glBufferData(,size,,) size->sizeof(vertexs)是数据大小不是偏移量大小
		glVertexAttribPointer (,,,,stride,);stride->sizeof(VX)是偏移量大小不是数据大小

}
           
{2:索引缓冲区 GL_ELEMENT_ARRAY_BUFFER
	OpenGL-ES 中 Vertex Arrays/Buffer Objects 在这个阶段发生

	unsigned ibId; //数据id
	{创建数据
		glGenBuffers(1,&ibId);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,ibId); //绑定/取消缓冲区
		glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(vertexs),vertexs,GL_STATIC_DRAW);//设置缓冲区数据
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); //绑定/取消缓冲区
	}

	{使用数据
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,ibId);//绑定/取消缓冲区
		glDrawElements(绘制模式,绘制数据大小,数据类型,);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);//绑定/取消缓冲区 注意:使用完就制空,OpenGL-ES是状态机
	}

	{code
		struct Vertex {
			float x, y, z;
			float u,v;
			float r, g, b,a;
		};
		Vertex positionData[] = {
			-1.0f, 1.0f,-1.0f,		0.0f,0.0f,     1.0f, 1.0f, 1.0f,1.0f, //  上左后
			-1.0f, 1.0f, 1.0f,		0.0f,1.0f,     1.0f, 1.0f, 1.0f,1.0f, //  上左前
			1.0f, 1.0f,-1.0f,		1.0f,0.0f,     1.0f, 1.0f, 1.0f,1.0f, //  上右后
			1.0f, 1.0f, 1.0f,		1.0f,1.0f,     1.0f, 1.0f, 1.0f,1.0f, //  上右前
			-1.0f,-1.0f,-1.0f,		0.0f,0.0f,     1.0f, 1.0f, 1.0f,1.0f, //  下左后
			-1.0f,-1.0f, 1.0f,		0.0f,1.0f,     1.0f, 1.0f, 1.0f,1.0f, //  下左前
			1.0f,-1.0f,-1.0f,		1.0f,0.0f,     1.0f, 1.0f, 1.0f,1.0f, //  下右后
			1.0f,-1.0f, 1.0f,		1.0f,1.0f,     1.0f, 1.0f, 1.0f,1.0f  //  下右前
		};
		byte indexData[]={
			0,1,2,2,3,1,  //上
			0,4,5,5,2,0,  //左
			0,4,6,6,2,0,  //后
			2,7,6,6,2,3,  //右
			1,5,7,7,2,1,  //前
			4,5,6,6,7,4,  //下
		};


		unsigned  vbId;//顶点缓冲区 id
		unsigned  ibId;//索引缓冲区 id

		//顶点缓冲区 id
		glGenBuffers(1,&vbId);
		glBindBuffer(GL_ARRAY_BUFFER,vbId);
		glBufferData(GL_ARRAY_BUFFER,sizeof(positionData),positionData,GL_STATIC_DRAW);
		glBindBuffer(GL_ARRAY_BUFFER,0);

		//索引缓冲区 id
		glGenBuffers(1,&ibId);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,ibId);
		glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indexData),indexData,GL_STATIC_DRAW);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);

		实例1
		glBindBuffer(GL_ARRAY_BUFFER,vbId);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,ibId);
		...
		glVertexAttribPointer(shader._position,3,  GL_FLOAT,   false,  sizeof(Vertex),(void*)0);
		glVertexAttribPointer(shader._tpos,    2,  GL_FLOAT,   false,  sizeof(Vertex),(void*)(3*sizeof(float)));
		glVertexAttribPointer(shader._color,   4,  GL_FLOAT,   false,  sizeof(Vertex),(void*)(3*sizeof(float)+2*sizeof(float)));

		glDrawElements(GL_TRIANGLES,sizeof(indexData)/sizeof(indexData[0]),GL_UNSIGNED_BYTE,0);

		glBindBuffer(GL_ARRAY_BUFFER,0);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);

		实例2
		...
		glVertexAttribPointer(shader._position,3,  GL_FLOAT,   false,  sizeof(Vertex),(void*)0);
		glVertexAttribPointer(shader._tpos,    2,  GL_FLOAT,   false,  sizeof(Vertex),(void*)(3*sizeof(float)));
		glVertexAttribPointer(shader._color,   4,  GL_FLOAT,   false,  sizeof(Vertex),(void*)(3*sizeof(float)+2*sizeof(float)));

		glDrawElements(GL_TRIANGLES,sizeof(indexData)/sizeof(indexData[0]),GL_UNSIGNED_BYTE,indexData);

		glBindBuffer(GL_ARRAY_BUFFER,0);

	}

}
           
{3:帧缓冲区 GL_FRAMEBUFFER/GL_RENDERBUFFER
	OpenGL-ES 中 Framebuffer 在这个阶段发生

	{
		1:创建一张帧缓冲大小
		2:把要画的东西画的一张纹理上(帧缓冲和纹理id绑定)
		3:渲染这种纹理
	}

	{code

		struct FBO{
			unsigned fb;//帧缓冲
			unsigned rb;//渲染缓冲
		};

		FBO createFBO(int width,int height){
			FBO frb;
			glGenFramebuffers(1,&frb.fb);//生成帧缓冲的索引
			glBindFramebuffer(GL_FRAMEBUFFER,frb.fb);//绑定帧缓冲

			glGenRenderbuffers(1,&frb.rb);//生成渲染缓冲的索引
			glBindRenderbuffer(GL_RENDERBUFFER,frb.rb);//绑定渲染缓冲

			/** 绘制渲染缓冲区的存储大小
			 * @param  target  类型(GL_RENDERBUFFER ...)
			 * @param  internalformat 存储数据格式(GL_DEPTH_COMPONENT16 深度信息)
			 * @param  width 存储的宽
			 * @param  height 存储的高
			 */
			glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT16,width,height);

			glBindRenderbuffer(GL_RENDERBUFFER,0);

			/** 帧缓冲区与渲染缓冲区绑定
			 * @param  target  帧缓冲区类型(GL_FRAMEBUFFER 帧缓冲区)
			 * @param  attachment  关联的类型(GL_DEPTH_ATTACHMENT 深度)
			 * @param  renderbuffertarget  渲染缓冲区类型(GL_RENDERBUFFER 渲染缓冲区)
			 * @param  renderbuffer  渲染缓冲区id
			 */
			glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER,frb.rb);

			glBindFramebuffer(GL_FRAMEBUFFER,0);

			return frb;
		}

		void beginFBO(unsigned fboId,uniform textureId){
			glBindFramebuffer(GL_FRAMEBUFFER,fboId);
			/** 帧缓冲区数据渲染到纹理上
			 * @param  target 帧缓冲类型(GL_RENDERBUFFER ...)
			 * @param  attachment 缓存区类型 (GL_COLOR_ATTACHMENT0 颜色缓存区)
			 * @param  textarget 纹理类型 (GL_TEXTURE_2D ...)
			 * @param  texture 纹理id
			 * @param  level 层级别(数据渲染到纹理的什么层级别上)
			 */
			glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,textureId,0);
		}
		void endFBO(){
			glBindFramebuffer(GL_FRAMEBUFFER,0);
		}

1:创建一张帧缓冲大小
		FBO  fboId;
		unsigned textureFboId;//帧缓冲数据保存到这张纹理上

		{//帧缓冲区
			fboId=createFBO(_width,_height);
			textureFboId=createTexture(_width,_height);
		}
2:把要画的东西画的一张纹理上(帧缓冲和纹理id绑定)
		beginFBO(fboId.fb,textureFboId);
			.... //所以要添加到帧缓冲的数据
		endFBO();
3:渲染这种纹理
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		//设置视口的大小
		glViewport(0,0,_width,_height);
		shader.begin();
				
			glBindTexture(GL_TEXTURE_2D,textureFboId);
			CELL::matrix4 mat=CELL::ortho<float>(0,(float)_width,(float)_height,0,-100,100);
			glUniformMatrix4fv(shader._MVP,1,false,mat.data());

			glVertexAttribPointer(shader._position,3,GL_FLOAT,false,sizeof(Vertex),&xt[0].pos);
			glVertexAttribPointer(shader._tpos,2,GL_FLOAT,false,sizeof(Vertex),&xt[0].uvpos);
			glVertexAttribPointer(shader._color,4,GL_FLOAT,false,sizeof(Vertex),&xt[0].rgba);
			glDrawArrays(GL_TRIANGLE_STRIP,0,sizeof(xt)/sizeof(xt[0]));

		shader.end();
	}

}
           
{4:封装
	VertexBuffer 顶点缓冲区  create,begin,end
	ElementBuffer 创建索引缓冲区  create,begin,end
	FrameBefferObject 帧缓冲  create,begin,end
}

//DataBuffer.hpp
#pragma once
#include "gles2/gl2.h"


class DataBuffer {
public:
	virtual~DataBuffer() {};
	virtual void begin() = 0;
	virtual void end() = 0;
	virtual void destroy() = 0;//销毁
protected:
	DataBuffer() {};
private:

};


/** 顶点缓冲区
*	struct VX{
*		float x, y, z;
*		float u,v;
*		float r, g, b,a;
*	};
*	VX vertexs[] ={
*		{ -1.0f,-1.0f, zOff,	0.0f,0.0f,	1.0f,1.0f, 1.0f,1.0f },
*		{  1.0f,-1.0f, zOff,	1.0f,0.0f,	1.0f,1.0f, 1.0f,1.0f }
*	}
*	//创建
*	VertexBuffer vbId=VertexBuffer::create(sizeof(vertexs),vertexs,GL_STATIC_DRAW);
*	//使用
*	vbId.begin();
*		...使用过程
*		glVertexAttribPointer(shader._position,3,  GL_FLOAT,   false,  sizeof(VX),(void*)0);
*		glVertexAttribPointer(shader._tpos,    2,  GL_FLOAT,   false,  sizeof(VX),(void*)(3*sizeof(float)));
*		//glVertexAttribPointer(shader._position,3,  GL_FLOAT,   false,  sizeof(VX),vertexs[0].x);
*		//glVertexAttribPointer(shader._tpos,    2,  GL_FLOAT,   false,  sizeof(VX),vertexs[0].u);
*	vbId.end();
*/
class VertexBuffer :public DataBuffer {
public:
	unsigned vbId;
public:
	virtual~VertexBuffer() {}

	/** 创建顶点缓冲区
	* @param  dataSize 数据大小
	* @param  data     数据
	* @param  dataType
	*		GL_STREAM_DRAW   偶尔需要改动数据
	*		GL_STATIC_DRAW   不改动(静态的)数据
	*		GL_DYNAMIC_DRAW  经常改动(动态的)数据
	* @return          [description]
	*/
	static VertexBuffer  create(int dataSize, void *data, int dataType = GL_STATIC_DRAW) {
		VertexBuffer vb;
		glGenBuffers(1, &vb.vbId);
		glBindBuffer(GL_ARRAY_BUFFER, vb.vbId); //绑定/取消缓冲区
		glBufferData(GL_ARRAY_BUFFER, dataSize, data, dataType);//设置缓冲区数据(更新全部数据)
		//glBufferSubData(GL_ARRAY_BUFFER, offset, size, data);//设置缓冲区数据(更新局部数据)
		glBindBuffer(GL_ARRAY_BUFFER, 0);//绑定/取消缓冲区
		return vb;
	}
	virtual void begin() {
		glBindBuffer(GL_ARRAY_BUFFER, vbId); //绑定/取消缓冲区
	}
	virtual void end() {
		glBindBuffer(GL_ARRAY_BUFFER, 0); //绑定/取消缓冲区
	}
	virtual void destroy() {
		glDeleteBuffers(1, &vbId);
	}
public:
	VertexBuffer() {}
};

/** 创建索引缓冲区
*	byte indexData[] = {
*		0, 1, 2, 2, 3, 0,  //上
*		0, 4, 5, 5, 1, 0,  //左
*		0, 4, 6, 6, 3, 0,  //后
*		2, 7, 6, 6, 3, 2,  //右
*		1, 5, 7, 7, 2, 1,  //前
*		4, 5, 7, 7, 6, 4,  //下
*	};
*
*	//创建
*	int drawSize = sizeof(indexData) / sizeof(indexData[0]);
*	ElementBuffer eb= ElementBuffer::create(drawSize,sizeof(indexData),indexData,GL_STATIC_DRAW);
*	//使用
*	eb.begin();
*		...使用过程(注意 顶点说索引同时使用eb.data 就不许添了,添0就可以了)
*		glDrawElements(GL_TRIANGLES, eb.drawSize, GL_UNSIGNED_BYTE, eb.data);
*	eb.end();
*/
class ElementBuffer :public DataBuffer {
public:
	unsigned ebId;
	int drawSize;//渲染数据个数
	void *data;//数据
public:
	virtual~ElementBuffer() {}

	/** 创建索引缓冲
	* @param  drawSize 渲染数据个数
	* @param  dataSize 数据大小
	* @param  data     数据
	* @param  dataType
	GL_STREAM_DRAW   偶尔需要改动数据
	GL_STATIC_DRAW   不改动(静态的)数据
	GL_DYNAMIC_DRAW  经常改动(动态的)数据
	* @return          [description]
	*/
	static ElementBuffer  create(int drawSize, int dataSize, void *data, int dataType = GL_STATIC_DRAW) {
		ElementBuffer eb;
		eb.drawSize = drawSize;
		eb.data = data;
		glGenBuffers(1, &eb.ebId);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eb.ebId); //绑定/取消缓冲区
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, dataSize, data, dataType);//设置缓冲区数据(更新全部数据)
		//glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, size, data);//设置缓冲区数据(更新局部数据)
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //绑定/取消缓冲区

		return eb;
	}
	virtual void begin() {
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebId); //绑定/取消缓冲区
	}
	virtual void end() {
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //绑定/取消缓冲区
	}
	virtual void destroy() { glDeleteBuffers(1, &ebId); }
public:
	ElementBuffer() {
		drawSize = -1;
		data = NULL;
	}

};

/** 帧缓冲
*	FrameBefferObject fboId=FrameBefferObject::create(100,100);
*	fboId.begin(textureFboId);
*		.... //所以要添加到帧缓冲的数据
*	fboId.end();
*	最后画这张 textureFboId 纹理就可以了
*/
class FrameBefferObject {
public:
	unsigned fb;//帧缓冲
	unsigned rb;//渲染缓冲

public:
	virtual ~FrameBefferObject() {}
	static FrameBefferObject  create(int width, int height) {
		FrameBefferObject frb;
		glGenFramebuffers(1, &frb.fb);//生成帧缓冲的索引
		glBindFramebuffer(GL_FRAMEBUFFER, frb.fb);//绑定帧缓冲

		glGenRenderbuffers(1, &frb.rb);//生成渲染缓冲的索引
		glBindRenderbuffer(GL_RENDERBUFFER, frb.rb);//绑定渲染缓冲

		/** 绘制渲染缓冲区的存储大小
		* @param  target  类型(GL_RENDERBUFFER ...)
		* @param  internalformat 存储数据格式(GL_DEPTH_COMPONENT16 深度信息)
		* @param  width 存储的宽
		* @param  height 存储的高
		*/
		glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);

		glBindRenderbuffer(GL_RENDERBUFFER, 0);

		/** 帧缓冲区与渲染缓冲区绑定
		* @param  target  帧缓冲区类型(GL_FRAMEBUFFER 帧缓冲区)
		* @param  attachment  关联的类型(GL_DEPTH_ATTACHMENT 深度)
		* @param  renderbuffertarget  渲染缓冲区类型(GL_RENDERBUFFER 渲染缓冲区)
		* @param  renderbuffer  渲染缓冲区id
		*/
		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, frb.rb);

		glBindFramebuffer(GL_FRAMEBUFFER, 0);

		return frb;
	}

	virtual void begin(unsigned textureId) {
		glBindFramebuffer(GL_FRAMEBUFFER, fb);
		/** 帧缓冲区数据渲染到纹理上
		* @param  target 帧缓冲类型(GL_RENDERBUFFER ...)
		* @param  attachment 缓存区类型 (GL_COLOR_ATTACHMENT0 颜色缓存区)
		* @param  textarget 纹理类型 (GL_TEXTURE_2D ...)
		* @param  texture 纹理id
		* @param  level 层级别(数据渲染到纹理的什么层级别上)
		*/
		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0);
	}

	virtual void end() {
		glBindFramebuffer(GL_FRAMEBUFFER, 0);
	}
	virtual void destroy() {
		glDeleteRenderbuffers(1, &rb);
		glDeleteFramebuffers(1, &fb);
	}
public:
	FrameBefferObject() {}

};
           

源码地址

http://pan.baidu.com/s/1geVargZ   缓冲区.zip

main.cpp
	//头文件不能都开,里面有重复定义的类或函数,不解释了自己看吧
	//#include "VertexBufferWin.hpp"
	//#include "ElementWin.hpp"
	#include "FraneBufferWin.hpp" 

	//VertexBufferWin app(hInstance);//顶点缓冲区数据
	//ElementWin app(hInstance);//索引缓冲区数据
	FraneBufferWin app(hInstance);//帧缓冲
           

帧缓冲效果图,就画的角上了,也可以全屏,代码住了,自己看吧(在渲染过程中)

OpenGLES---缓冲区

继续阅读