索引緩沖對象(Element Buffer Objects,EBO)
為什麼使用EBO
正常畫一個立方體,需要8個頂點,合計6個面
但實際我們是用了4*6=24個點來畫的,因為4個點組成一個面,我們能看出來,有很多重複點,為了能節省記憶體空間,我們想隻用8個點描畫立方體,這需要用到EBO
VertexData vc[] = {
//正面
{QVector3D(-0.5f, 0.0f, 0.5f), QVector3D(1.0f, 0.0f, 0.0f)}, //1
{QVector3D(0.5f, 0.0f, 0.5f), QVector3D(0.0f, 1.0f, 0.0f)}, //2
{QVector3D(0.5f, 1.0f, 0.5f), QVector3D(0.0f, 0.0f, 1.0f)}, //3
{QVector3D(-0.5f, 1.0f, 0.5f), QVector3D(1.0f, 1.0f, 1.0f)}, //4
//右面
{QVector3D(0.5f, 0.0f, 0.5f), QVector3D(0.0f, 1.0f, 0.0f)}, //2
{QVector3D(0.5f, 0.0f, -0.5f), QVector3D(1.0f, 1.0f, 0.0f)}, //5
{QVector3D(0.5f, 1.0f, -0.5f), QVector3D(0.0f, 1.0f, 1.0f)}, //6
{QVector3D(0.5f, 1.0f, 0.5f), QVector3D(0.0f, 0.0f, 1.0f)}, //3
//左面
{QVector3D(-0.5f, 0.0f, 0.5f), QVector3D(1.0f, 0.0f, 0.0f)}, //1
{QVector3D(-0.5f, 0.0f, -0.5f),QVector3D(1.0f, 0.0f, 1.0f)}, //8
{QVector3D(-0.5f, 1.0f, -0.5f),QVector3D(1.0f, 0.6f, 0.0f)}, //7
{QVector3D(-0.5f, 1.0f, 0.5f), QVector3D(1.0f, 1.0f, 1.0f)}, //4
//背面
{QVector3D(0.5f, 0.0f, -0.5f), QVector3D(1.0f, 1.0f, 0.0f)}, //5
{QVector3D(0.5f, 1.0f, -0.5f), QVector3D(0.0f, 1.0f, 1.0f)}, //6
{QVector3D(-0.5f, 1.0f, -0.5f), QVector3D(1.0f, 0.6f, 0.0f)}, //7
{QVector3D(-0.5f, 0.0f, -0.5f), QVector3D(1.0f, 0.0f, 1.0f)}, //8
//頂面
{QVector3D(0.5f, 1.0f, 0.5f), QVector3D(0.0f, 0.0f, 1.0f)}, //3
{QVector3D(0.5f, 1.0f, -0.5f), QVector3D(0.0f, 1.0f, 1.0f)}, //6
{QVector3D(-0.5f, 1.0f, -0.5f), QVector3D(1.0f, 0.6f, 0.0f)}, //7
{QVector3D(-0.5f, 1.0f, 0.5f), QVector3D(1.0f, 1.0f, 1.0f)}, //4
//底面
{QVector3D(0.5f, 0.0f, 0.5f), QVector3D(0.0f, 1.0f, 0.0f)}, //2
{QVector3D(0.5f, 0.0f, -0.5f), QVector3D(1.0f, 1.0f, 0.0f)}, //5
{QVector3D(-0.5f, 0.0f, -0.5f), QVector3D(1.0f, 0.0f, 1.0f)}, //8
{QVector3D(-0.5f, 0.0f, 0.5f), QVector3D(1.0f, 0.0f, 0.0f)}, //1
};
EBO原理
//頂點有8個
VertexData vcs[] = {
//正面
{QVector3D(-0.5f, 0.0f, 0.5f), QVector3D(1.0f, 0.0f, 0.0f)}, //1
{QVector3D(0.5f, 0.0f, 0.5f), QVector3D(0.0f, 1.0f, 0.0f)}, //2
{QVector3D(0.5f, 1.0f, 0.5f), QVector3D(0.0f, 0.0f, 1.0f)}, //3
{QVector3D(-0.5f, 1.0f, 0.5f), QVector3D(1.0f, 1.0f, 1.0f)}, //4
{QVector3D(0.5f, 0.0f, -0.5f), QVector3D(1.0f, 1.0f, 0.0f)}, //5
{QVector3D(0.5f, 1.0f, -0.5f), QVector3D(0.0f, 1.0f, 1.0f)}, //6
{QVector3D(-0.5f, 1.0f, -0.5f),QVector3D(1.0f, 0.6f, 0.0f)}, //7
{QVector3D(-0.5f, 0.0f, -0.5f),QVector3D(1.0f, 0.0f, 1.0f)}, //8
};
//索引 對應8個面,每個面說明使用哪4個頂點
GLuint indices[] = { // 起始于0!
0, 1, 2, 3, // face 1
1, 4, 5, 2, // face 2
0, 7, 6, 3, // face 3
4, 5, 6, 7, // face 4
2, 5, 6, 3, // face 5
1, 4, 7, 0, // face 6
};
代碼順序
建立
//1 使用glGenBuffers函數生成一個緩沖ID
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
綁定VAO
//2 綁定vao
glBindVertexArray(VAO);
綁定VBO,EBO
//3 使用glBindBuffer函數把新建立的緩沖綁定到GL_ARRAY_BUFFER緩沖類型上
glBindBuffer(GL_ARRAY_BUFFER, VBO); //(綁定和解綁的順序很重要,勿更改)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
複制資料
//4 把使用者定的義資料複制到目前綁定緩沖的函數
glBufferData(GL_ARRAY_BUFFER, sizeof(vcs), vcs, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
連結屬性
//5 連結頂點屬性
//indx: 屬性名
//size: 頂點大小
//type: 資料類型
//normalized:資料被标準化
//stride: 步長
//ptr: 資料在緩沖中起始位置的偏移量
glVertexAttribPointer(m_posAttr, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (GLvoid*)0);
glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (GLvoid*)sizeof(QVector3D));
解綁 VBO
//6 解綁緩存着色器(綁定和解綁的順序很重要,勿更改)
glBindBuffer(GL_ARRAY_BUFFER, 0);
解綁VAO
//7 解綁VAO
glBindVertexArray(0);
PS: 這裡我颠倒了順序,并沒有出現問題,可能qt給優化過,不解綁也沒事,另外EBO不用解綁,就算要解綁,也要在VAO解綁後
繪制過程
綁定vao
//1 綁定vao
glBindVertexArray(VAO);
開啟屬性
//2 開啟頂點屬性
glEnableVertexAttribArray(0);
//顔色值
glEnableVertexAttribArray(1);
繪制四邊形
//3 繪制四邊形
//24個索引值
glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, (GLvoid*)0);
停用屬性
//4 停用對應的頂點屬性數組
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
解綁VAO
//5 解綁VAO
glBindVertexArray(0);
源代碼
https://gitee.com/chen227/opengl_OpenGLFunctions5