{
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);//幀緩沖
幀緩沖效果圖,就畫的角上了,也可以全屏,代碼住了,自己看吧(在渲染過程中)