OpenGL中主要包括了兩種數據——Buffer和Texture。
Buffer用於儲存線性數無類型據塊,可以看成普通的內存塊,而Texture則用於儲存多維數據,一般儲存圖像或者其他數據。
Buffer
OpenGL中有很多綁定點,Buffer綁定在綁定點使用。
使用glGenBuffers來生成一個Buffer的id。
使用glBindBuffer來綁定一個Buffer。
使用glBufferData來為Buffer分配內存。如果想要改變Buffer中已經初始化的數據,那么可以使用glBufferSubData。
如果想要從Buffer中拷貝或者寫入數據,glMapBuffer會返回一個這些數據的指針,可以使用memcpy進行數據拷貝寫入等等操作,使用完成后使用glUnmapBuffer來解除。
值得注意的是:所有的Buffer Object都只是一個中間的管理平台,與實際的空間相分離。其中,除了FBO所關聯的數據空間在顯存之外,PBO和VBO所關聯的數據空間位置均不一定 (system memory, shared memory, AGP, Video Memory均有可能)。

如果只是希望將緩存對象的數據清除為一個已知的值,那么也可以使用glClearBufferData()或者glClearBufferSubData()函數。清除緩存對象中所有或者部分數據。綁定到target的緩存存儲空間將使用data中存儲的數據進行填充。format和type分別指定了data對應數據的格式和類型。glClearBufferData()和glClearBufferSubData()函數允許我們初始化緩存對象中存儲的數據,並且不需要保留或者清除任何一處系統內存。
緩存對象中的數據也可以使用glCopyBufferSubData()函數互相進行拷貝。
glCopyBufferSubData()可以在兩個目標對應的緩存之間拷貝數據,而GL_COPY_READ_BUFFER和 GL_COPY_WRITE_BUFFER這兩個目標正是為了這個目的而生。它們不能用於其他OpenGL的操作當中,並且如果將緩存與它們進行綁定,並 且只用於數據的拷貝和存儲目的,不影響OpenGL的狀態也不需要記錄拷貝之前的目標區域信息的話,那么整個操作過程都是可以保證安全的。
使用glGetBufferSubData()函數可以從綁定到某個目標的緩存中回讀數據,然后將它放置到應用程序保有的一處內存當中。我們也可以使用glGetBufferSubData()簡單地將之前存入到緩存對象中的數據讀回到內存中。
使用Buffer填充頂點shader
創建綁定vao,然后使用glVertexAttribPointer來指定了渲染時索引值為 index 的頂點屬性數組的數據格式和位置。當數組中的值被訪問並被轉換至浮點值時,如果normalized被設置為GL_TRUE,意味着整數型的值會被映射至區間[-1,1](有符號整數),或者區間[0,1](無符號整數),反之,這些值會被直接轉換為浮點值而不進行歸一化處理。glVertexAttribPointer的stride參數指定了每個數據之間的間距,如果是0,並不意味着間距是0,而是提示OpenGL 數據是緊密排列的,openGL將根據輸出的size等參數自行計算間距。間距的計算即是:每個數據開頭的地址到下一個數據開頭地址的字節數。
要啟用或者禁用頂點屬性數組,調用glEnableVertexAttribArray和glDisableVertexAttribArray傳入參數index。如果啟用,那么當glDrawArrays或者glDrawElements被調用時,頂點屬性數組會被使用。
關於使用vbo和ibo綁定vao 索引繪制的實例:
//讀取數據
GLushort index[65535]; int index_size = 0; GLfloat vert[65535]; int vert_size = 0; GLuint gebo; GLuint gvao; GLuint gvbo; std::fstream f1, f2; std::string s; int k = 0; f2.open("media/models/1.tri ", std::ios::in); f1.open("media/models/1.vert", std::ios::in); while (getline(f1, s)) {
sscanf(s.data(), "%f %f %f", &vert[k], &vert[k + 1], &vert[k + 2]); k += 3; vert_size += 3; } f1.clear(); k = 0; while (getline(f2, s))
{ sscanf(s.data(), "%d %d %d", &index[k], &index[k + 1], &index[k + 2]); --index[k + 1]; --index[k + 2]; --index[k]; k += 3; index_size += 3; } //生成vbo,ibo,vao,並且綁定vao
glGenBuffers(1, &gvbo); glBindBuffer(GL_ARRAY_BUFFER, gvbo); glBufferData(GL_ARRAY_BUFFER, vert_size*sizeof(float), vert, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); glGenBuffers(1, &gebo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gebo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_size*sizeof(GLushort), index, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glGenVertexArrays(1, &gvao); glBindVertexArray(gvao); glBindBuffer(GL_ARRAY_BUFFER, gvbo); //設置vbo數據格式
glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, 0, 0); //啟用此屬性數組
glEnableVertexAttribArray(7); //綁定ibo到vao
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gebo); //索引不傳入shader所以不用glVertexAttribPointer等函數 //不要此處不能解綁vbo和ibo
glBindVertexArray(0); //draw
glUseProgram(program); glUniformMatrix4fv(proj_location2, 1, GL_FALSE, proj_matrix); glUniformMatrix4fv(mv_location2, 1, GL_FALSE, mv_matrix); glBindVertexArray(gvao); //此處直接使用drawcall,不用再做任何設置
glDrawElements(GL_LINES, index_size, GL_UNSIGNED_SHORT, 0);
Shader:
//vertex
#version 410 core layout (location = 7) in vec4 position; uniform mat4 mv_matrix; uniform mat4 proj_matrix; void main(void) { gl_Position = proj_matrix * mv_matrix * position; } //fragement
#version 410 core out vec4 color; void main() { color = vec4(1,0,0,1); }
