{
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);//帧缓冲
帧缓冲效果图,就画的角上了,也可以全屏,代码住了,自己看吧(在渲染过程中)