Outline 一般繪圖方式 硬體加速繪圖方式 Display List Vertex Array 序列式 : gldrawarrays 索引式 : gldrawelements Vertex Buffer Object (VBO) 序列式 索引式 Callback Function 2014/12/18 2
一般繪圖方式 glbegin(gl_triangles); for(int i = 0; i < ntriangles; ++i) { } glnormal3fv(triarray[i].n); glvertex3fv(triarray[i].a); glvertex3fv(triarray[i].b); glvertex3fv(triarray[i].c); glend(); 2014/12/18 3
Display List 預先將一連串的繪圖指令編譯並儲存, 在需要使用時再行呼叫 初始化 Gluint _DisplayList = glgenlists(1); glnewlist(_displaylist, GL_COMPILE); ( 一般繪圖方式或想儲存的 OpenGL 函數 ) glendlist(); 繪圖時 glcalllist(_displaylist); 清除 gldeletelists(_displaylist, 1); 2014/12/18 4
Display List 無法在 Display List 中儲存的 OpenGL 函數 2014/12/18 5
Display List 階層式 Display List glnewlist(a); glcalllist(b); gltranslatef(1.0, 0.0, 0.0); glcalllist(c); gltranslatef(1.0, 0.0, 0.0); glcalllist(c); glendlist(); 不能在 glnewlist/glendlist 之間, 包入 glnewlist/glendlist, 但可以 glcalllist 階層限制為 64, 不過這取決於 OpenGL 的實作, 可調用函式來查看階層上限 glgetintegerv(gl_max_list_nesting, GLint *data); 2014/12/18 6
Vertex Array OpenGL 原生支援的頂點陣列啟用 / 關閉 glenableclintstate(glenum array); gldisableclientstate(glenum array); GL_VERTEX_ARRAY GL_NORMAL_ARRAY 指定 Array 的數據 glvertexpointer(glint size, GLenum type, GLsizei stride, const GLvoid *pointer); size: 每個頂點的座標數量, 必須為 2 3 或 4 type: 座標的數據類型 (GL_SHORT GL_INT ) stride: 連續的頂點之間的偏移量 彩現 pointer: 第一個頂點的第一個座標的地址 2014/12/18 7
Vertex Array- 彩現方式 索引式 : 能隨機呼叫 glarrayelement gldrawelements glmultidrawelements gldrawrangeelements 序列式 : 只能依序呼叫 gldrawarrays glmultidrawarrays 2014/12/18 8
索引式 Vertex Array 以索引值的陣列來指定物件使用的座標點 不必重複儲存重複的座標點 減少傳遞到顯示卡的記憶體量, 以提高運作效率 2014/12/18 9
索引式 Vertex Array (conti.) 2014/12/18 10
Vertex Array- 索引式彩現方式 glarrayelement glenableclientstate(gl_vertex_array); glvertexpointer(2, GL_INT, 0, data); glbegin(gl_triangles) glarrayelement(2); glarrayelement(5); glarrayelement(8); glend(); gldrawelements gldrawelements(mode, count, type, index); glmultidrawelements for(i=0; i<primcount; i++) if(count[i]>0) gldrawelements(mode, count[i], type, index[i]); glbegin(gl_triangles) glvertex2iv(data+(2*2)); glvertex2iv(data+(5*2)); glvertex2iv(data+(8*2)); glend(); glbegin(mode) for(i=0; i<count; i++) glarrayelement(index[i]); glend(); 2014/12/18 11
Vertex Array- 序列式彩現方式 gldrawarrays gldrawarrays(mode, first, count); glbegin(mode) for(i=0; i<count; i++) glarrayelement(first+i); glend(); glmultidrawarrays for(i=0; i<primcount; i++) if(count[i]) gldrawarrays(mode, first[i], count[i]); 2014/12/18 12
Vertex Buffer Object (VBO) VBO 是 OpenGL 提供給使用者的一個將 vertex data( 包含 position, normal vector, color, etc.) 非即時地上傳到顯示卡記憶體的方法 由於 vertex data 是儲存於顯示卡記憶體, 因此, 相較於其他 render 方式, 具有更高的效能 自 OpenGL 1.5 之後成為標準 2014/12/18 13
Vertex Buffer Object 建立 Buffer Object GLuint _VBO[2]; glgenbuffers(2, _VBO); 綁定 Buffer Object glbindbuffer(glenum target, GLuint buffer); Vertex 資料到 Buffer Object 內 glbufferdata(...); 更新 Buffer Object glbuffersubdata(...); glmapbuffer(...) glunmapbuffer(...) 清除 Buffer Object gldeletebuffers(glsizei n, GLuint *buffer); 2014/12/18 14
Vertex Buffer Object Bind Buffer glbindbuffer(glenum target, GLuint buffer); target: GL_ARRAY_BUFFER GL_ELEMENT_ARRAY_BUFFER buffer: 指定將綁定的 Buffer Object ( 如 :_VBO[0]) glbindbuffer 有三個功用 當 buffer 為首次使用之非零 UINT 時 建立一個新的 Buffer Object, 並將 buffer 分配給此 Buffer Object 當作名稱 當綁定到一個以前建立的 Buffer Object 時 設定此 Buffer Object 為 Active 當綁定到一個值為零的 buffer 時 OpenGL 會停止使用 Buffer Object 2014/12/18 15
Vertex Buffer Object Buffer Data glbufferdata(glenum target, GLsizeiptr size, const GLvoid *data, GLenum usage) 分配 size 個儲存單位 (byte) 的 OpenGL Device Memory, 用於儲存頂點或索引數據 以前所有與當前綁定對象相關聯的數據都將被刪除 target: GL_ARRAY_BUFFER( 頂點數據 ) GL_ELEMENT_ARRAY_BUFFER( 索引數據 ) GL_PIXEL_UNPACK_BUFFER( 傳遞給 OpenGL 的像素數據 ) GL_PIXEL_PACK_BUFFER( 從 OpenGL 獲取的像素數據 ) size: 儲存相關數據所需的記憶體空間 ( 通常是元素個數 各自儲存長度 ) data: 指向主記憶體中相關數據的指標 ( 用於初始化 Buffer Object) usage:gl_static_draw GL_DYNAMIC_READ GL_STREAM_COPY STATIC: 在 VBO 中的資料將不會改變 ( 指定一次多次使用 ) DYNAMIC: 資料將經常改變 ( 反覆指定與使用 ) STREAM: 資料在每個 Frame 都會改變 ( 一次指定一次使用 ) DRAW: 資料送到 GPU 繪出 ( 應用程式 GL) READ: 資料會被讀取到應用程式 (GL 應用程式 ) COPY: 資料會被 DRAW 與 READ(GL GL) 用於 PBO or FBO 2014/12/18 16
Vertex Buffer Object Update Buffer void glbuffersubdata(glenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data); 以 data 所指向的資料替換掉 target 所指向的資料, 從 offset 開始的 size 個 byte void *glmapbuffer(glenum target, GLenum access); GLboolean glunmapbuffer(glenum target); 透過 glmapbuffer 取得 buffer 的指標 針對該 buffer 進行修改 調用 glunmapbuffer 通知 OpenGL 已經完成修改 2014/12/18 17
Callback Function 2014/12/18 18