VBO:顶点缓冲区 IBO:索引缓冲区
VBO的作用:在不使用VBO的情况下,每次调用glDrawArrays或glDrawElements的时候,都要把数据从内存拷贝到显卡,频繁的绘制内存和显卡之间就要频繁的拷贝数据这会增加很多开销,而VBO就是把要绘制的顶点信息直接缓存在显卡内存中,这样就避免了内存和显卡的频繁交互,在绘制复杂模型时可以降低很多开销,提高性能。
IBO和VBO原理类似,只不过IBO是缓存了VBO绘制时的Indices。
根据Opengles2.0 官方建议,将VBO和IBO结合使用,能获得比较好的性能。
VBO和IBO的使用
unsigned _vbo;
unsigned _indexbo;
//顶点信息
struct Vertex
{
float x, y, z;
float u, v;
float r, g, b, a;
};
//顶点数组 x,y,z u,v r,g,b,a 一共8个顶点
Vertex cubeVerticesIndexed[] =
{
{ -1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,0.0f, 1.0f }, // 0
{ 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }, // 1
{ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }, // 2
{ -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }, // 3
{ -1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }, // 4
{ -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }, // 5
{ 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }, // 6
{ 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }, // 7
};
//顶点索引数组
//正方体共6个面,每个面是四边形,由两个三角形组成
//比如第0个面,由0,1,2这个三角形和0,2,3这个三角形组成
GLubyte indexBuf[] =
{
0, 1, 2, 0, 2, 3, // Quad 0 第一个面索引
4, 5, 6, 4, 6, 7, // Quad 1 第二个面索引
5, 3, 2, 5, 2, 6, // Quad 2 第三个面索引
4, 7, 1, 4, 1, 0, // Quad 3 第四个面索引
7, 6, 2, 7, 2, 1, // Quad 4 第五个面索引
4, 0, 3, 4, 3, 5 // Quad 5 第六个面索引
};
//根据opengles2.0 "Golden Book" 的建议,要想获得好的性能,就要尽可能使用VBO和IBO来完成绘制任务
//IBO跟VBO原理类似,只不过IBO是缓存了VBO绘制时的Indices
glGenBuffers(1, &_vbo);//创建vbobuffer
glBindBuffer(GL_ARRAY_BUFFER, _vbo);//绑定buffer
//将数据上传到显存
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVerticesIndexed), cubeVerticesIndexed, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);//解除绑定
glGenBuffers(1, &_indexbo);//创建ibobuffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexbo);//指定buffer类型
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexBuf), indexBuf, GL_STATIC_DRAW); //上传数据到buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);//解除绑定
//使用VBO和IBO进行绘制
glBindBuffer(GL_ARRAY_BUFFER, _vbo); //绑定之前创建好的VBO
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexbo);//绑定之前创建好的IBO
glUniformMatrix4fv(_shader._MVP, 1, false, MVP1.data());
glVertexAttribPointer(_shader._positionAttr, 3, GL_FLOAT, false, sizeof(Vertex), (void*)0);//顶点坐标起始位置
glVertexAttribPointer(_shader._uvAttr, 2, GL_FLOAT, false, sizeof(Vertex), (void*)12);//纹理坐标起始位置
glVertexAttribPointer(_shader._colorAttr, 4, GL_FLOAT, false, sizeof(Vertex), (void*)20);//颜色坐标起始位置
//使用IBO指定的36个索引来绘制
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, 0);
//glDrawArrays(GL_TRIANGLES,0,6);
glBindBuffer(GL_ARRAY_BUFFER, 0);//解除VBO绑定
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);//解除IBO绑定
窗口实现类
#pragma once
#include <Windows.h>
#include <tchar.h>
#include <math.h>
#include <EGL/egl.h>
#include <gles2/gl2.h>
#include "freeImage/FreeImage.h"
#include "CELLMath.hpp"
#include "CELLShader.hpp"
namespace CELL
{
class FirstCameraInfor
{
public:
FirstCameraInfor()
{
_moveSpeed = 5;
_eye = CELL::float3(0.0f, 10.0f, 0.0f);
_look = CELL::float3(0.5f, -0.4f, -0.5f);
_up = CELL::float3(0, 1, 0);
_right = CELL::float3(1, 0, 0);
}
CELL::float3 _eye;
CELL::float3 _look;
CELL::float3 _up;
CELL::float3 _right;
float _moveSpeed;
public:
void updateCamera(float fElapsed)
{
CELL::float3 tmpLook = _look;
CELL::float3 dir = _look - _eye;
dir = normalize(dir)