18. chapter#11_render_20141216

18

Upload: jackfin

Post on 07-Feb-2016

213 views

Category:

Documents


0 download

DESCRIPTION

C++ opengl render

TRANSCRIPT

Page 1: 18. Chapter#11_Render_20141216
Page 2: 18. Chapter#11_Render_20141216

Outline

一般繪圖方式

硬體加速繪圖方式 Display List Vertex Array○ 序列式: glDrawArrays○ 索引式: glDrawElements

Vertex Buffer Object (VBO)○ 序列式

○ 索引式

Callback Function

2014/12/18 2

Page 3: 18. Chapter#11_Render_20141216

一般繪圖方式

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

Page 4: 18. Chapter#11_Render_20141216

Display List

預先將一連串的繪圖指令編譯並儲存,在需要使用時再行呼叫

初始化 Gluint _DisplayList = glGenLists(1); glNewList(_DisplayList, GL_COMPILE);

… (一般繪圖方式或想儲存的OpenGL函數) glEndList();

繪圖時 glCallList(_DisplayList);

清除 glDeleteLists(_DisplayList, 1);

2014/12/18 4

Page 5: 18. Chapter#11_Render_20141216

Display List

無法在Display List中儲存的OpenGL函數

2014/12/18 5

Page 6: 18. Chapter#11_Render_20141216

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

Page 7: 18. Chapter#11_Render_20141216

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

Page 8: 18. Chapter#11_Render_20141216

Vertex Array-彩現方式

glArrayElement

glDrawElements

glMultiDrawElements

glDrawRangeElements

glDrawArrays

glMultiDrawArrays

2014/12/18 8

索引式:能隨機呼叫 序列式:只能依序呼叫

Page 9: 18. Chapter#11_Render_20141216

索引式Vertex Array

以索引值的陣列來指定物件使用的座標點

不必重複儲存重複的座標點

減少傳遞到顯示卡的記憶體量,以提高運作效率

2014/12/18 9

Page 10: 18. Chapter#11_Render_20141216

索引式Vertex Array (conti.)

2014/12/18 10

Page 11: 18. Chapter#11_Render_20141216

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]);

Page 12: 18. Chapter#11_Render_20141216

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();

Page 13: 18. Chapter#11_Render_20141216

Vertex Buffer Object (VBO)

VBO是OpenGL提供給使用者的一個將vertex data(包含position, normal vector, color, etc.)非即時地上傳到顯示卡記憶體的方法

由於vertex data是儲存於顯示卡記憶體,因此,相較於其他render方式,具有更高的效能

自OpenGL 1.5之後成為標準

2014/12/18 13

Page 14: 18. Chapter#11_Render_20141216

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

Page 15: 18. Chapter#11_Render_20141216

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

Page 16: 18. Chapter#11_Render_20141216

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

Page 17: 18. Chapter#11_Render_20141216

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

Page 18: 18. Chapter#11_Render_20141216

Callback Function

2014/12/18 18