18. chapter#11_render_20141216
DESCRIPTION
C++ opengl renderTRANSCRIPT
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 ListglNewList(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
glDrawElements
glMultiDrawElements
2014/12/18 11
glEnableClientState(GL_VERTEX_ARRAY);glVertexPointer(2, GL_INT, 0, data);glBegin(GL_TRIANGLES)
glArrayElement(2);glArrayElement(5);glArrayElement(8);
glEnd();
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();
glDrawElements(mode, count, type, index);
for(i=0; i<primcount; i++)if(count[i]>0)glDrawElements(mode, count[i], type, index[i]);
Vertex Array-序列式彩現方式
glDrawArrays
glMultiDrawArrays
2014/12/18 12
glDrawArrays(mode, first,count);
for(i=0; i<primcount; i++)if(count[i])glDrawArrays(mode, first[i], count[i]);
glBegin(mode)for(i=0; i<count; i++)
glArrayElement(first+i);glEnd();
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 ObjectGLuint _VBO[2];glGenBuffers(2, _VBO);
綁定Buffer ObjectglBindBuffer(GLenum target, GLuint buffer);
Vertex資料到Buffer Object內glBufferData(...);
更新Buffer ObjectglBufferSubData(...);glMapBuffer(...)、glUnmapBuffer(...)
清除Buffer ObjectglDeleteBuffers(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分配給此BufferObject當作名稱
當綁定到一個以前建立的Buffer Object時
○ 設定此Buffer Object為Active
當綁定到一個值為零的buffer時
○ OpenGL會停止使用Buffer Object
2014/12/18 15
Vertex Buffer Object – Buffer Data
glBufferData(GLenum target, GLsizeiptrsize, 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)2014/12/18 16
用於PBO or FBO
Vertex Buffer Object – Update Buffer
void glBufferSubData(GLenum target, GLintptroffset, GLsizeiptr size, const GLvoid* data); 以data所指向的資料替換掉target所指向的資料,從offset開始的size個byte
void *glMapBuffer(GLenum target, GLenumaccess);
GLboolean glUnmapBuffer(GLenum target); 透過glMapBuffer取得buffer的指標
針對該buffer進行修改
調用glUnmapBuffer通知OpenGL已經完成修改
2014/12/18 17
Callback Function
2014/12/18 18