420 likes | 645 Views
Sierpinski Gasgets. 靜宜大學資工系 蔡奇偉副教授. 大綱. OpenGL 的命名慣例 Sierpinski Gasgets GLUT 初始化函 式 初始化 glew 事件 驅動程式 Create a vertex array object Create and initialize a buffer object Load and use shader programs Initialize vertex position attribute Display. OpenGL 的命名慣例.
E N D
SierpinskiGasgets 靜宜大學資工系 蔡奇偉副教授
大綱 • OpenGL 的命名慣例 • SierpinskiGasgets • GLUT 初始化函式 • 初始化 glew • 事件驅動程式 • Create a vertex array object • Create and initialize a buffer object • Load and use shaderprograms • Initialize vertex position attribute • Display
OpenGL 的命名慣例 • 函式名稱以 gl開頭,而且名稱中每個字的字首使用大寫,如 glClearColor()。 • 常數名稱全為大寫字母並以 GL 開頭,名稱中每個字用底線字元(_) 隔開,如 GL_COLOR_BUFFER_BIT。 • 某些函式的字尾暗示參數的個數與型態,如glVertex3f (float x, float y, float z) /* 3 個浮點數 */ glVertex2i (int x, int y) /* 2 個整數 */ glVetex3fv (float *vl) /* 3 個浮點數組成的陣列 */
字尾 資料型態 OpenGL 資料型態 b signed char GLbyte s short GLshort i int (or long) GLint, GLsizei f float GLfloat, GLclampf d double GLdouble, GLclampd ub unsigned char GLubyte, GLboolean us unsigned short GLushort ui unsigned int GLuint, GLenum, GLbitfield (or unsigned long) 此外,參數為陣列的函式通常以字母 v 為結尾。
查詢 OpenGL 的版本資訊 constGLubyte *glGetString(GLenum name); • GL_VERSION • 傳回 OpenGL 的版本字串。可為以下兩種格式: • major.minor • major.minor.release • GL_VENDOR • 傳回 OpenGL 硬體的製造廠名稱。
code to generate points • constintNumPoints = 50000; • vec2 points[NumPoints]; • // Specifiy the vertices for a triangle • vec2 vertices[3] = { • vec2( -1.0, -1.0 ), vec2( 0.0, 1.0 ), vec2( 1.0, -1.0 )}; • // Select an arbitrary initial point inside of the triangle • points[0] = vec2( 0.25, 0.50 ); • // compute and store N-1 new points • for ( inti = 1; i < NumPoints; ++i ) { • intj = rand() % 3; // pick a vertex at random • // Compute the point halfway between the selected vertex • // and the previous point • points[i] = ( points[i - 1] + vertices[j] ) / 2.0; • }
main Procedure #include "Angel.h“ int main( intargc, char **argv ) { glutInit( &argc, argv ); glutInitDisplayMode( GLUT_RGBA ); glutInitWindowSize( 512, 512 ); // If you are using freeglut, the next two lines will check if // the code is truly 3.2. Otherwise, comment them out glutInitContextVersion( 3, 2 ); glutInitContextProfile( GLUT_CORE_PROFILE );
glutCreateWindow( "Sierpinski Gasket" ); glewExperimental=GL_TRUE; GLenum err=glewInit(); if(err!=GLEW_OK) { // Problem: glewInit failed, something is seriously wrong. std::cout<<"glewInit failed, aborting."<<std::endl; } init(); glutDisplayFunc( display ); glutKeyboardFunc( keyboard ); glutMainLoop(); return 0; }
GLUT 初始化函式 • glutInit (int*argc, char ** argv) • 設定啟動 GLUT 所需的初值,然後處理一些指令行的參數(用於 X Window 系統)。呼叫這個函式後才能夠開始呼叫其他的 GLUT 函式。
glutInitDisplayMode (unsigned intmode) • 設定顯示的模式。你可以用 bitwise OR(|)的方式來選取以下的模式 : • GLUT_RGBA(或 GLUT_RGB), GLUT_INDEX • GLUT_SINGLE, GLUT_DOUBLE • GLUT_ACCUM • GLUT_ALPHA • GLUT_DEPTH • GLUT_STENCIL • GLUT_LUMINANCE • GLUT_MULTISAMPLE
Multisampling • glutInitDisplayMode( GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA | GLUT_MULTISAMPLE); • glEnable(GL_MULTISAMPLE) w/o multisampling with multisampling
glutInitWindowSize (intwidth, intheight) 設定視窗的初始大小為 width x height像素。 glutInitWindowPosition (int x, int y) 設定視窗在螢幕上的初始位置為 (x, y) 像素。 glutCreateWindow (char *name) 建立和顯示最上層的視窗並把視窗的標題設成 name。
glutInitContextVersion( int major, int minor ); • 設定執行環境的版本為 major.minor,譬如: • glutInitContextVersion(3, 2); • 設定執行環境的版本為 3.2。
glutInitContextProfile( int profile ) • 設定執行環境的模式為: • GLUT_CORE_PROFILE 或 • GLUT_COMPATIBILITY_PROFILE • 前者適用於 3.1 版與之後的新式 OpenGL API,後者適用於 2.x 版的舊式 API。
glutInitContextFlags ( GLuint flags) • 設定執行環境的選項為: • GLUT_DEBUG • GLUT_FORWARD_COMPATIBLE • 前者啟用偵錯功能,後者將限制程式只能用新式的 OpenGL API。
初始化 glew • glewExperimental= GL_TRUE; • GLenum err = glewInit(); • if(err != GLEW_OK) • { • //Problem: glewInit failed, something is seriously wrong. • std::cout<<"glewInit failed, aborting."<<std::endl; • exit(-1); • }
Experimental Drivers GLEW obtains information on the supported extensions from the graphics driver. Experimental or pre-release drivers, however, might not report every available extension through the standard mechanism, in which case GLEW will report it unsupported. To circumvent this situation, the glewExperimentalglobal switch can be turned on by setting it to GL_TRUE before calling glewInit(), which ensures that all extensions with valid entry points will be exposed.
void display ( void ) { glClear( GL_COLOR_BUFFER_BIT ); // clear the window glDrawArrays( GL_POINTS, 0, NumPoints ); // draw the points glFlush(); } void keyboard ( unsigned char key, int x, int y ) { switch ( key ) { case 033: exit( EXIT_SUCCESS ); break; } } int main( intargc, char **argv ) { // Initialization … glutDisplayFunc( display ); glutKeyboardFunc( keyboard ); glutMainLoop(); return 0; }
事件驅動程式 目前流行的視窗系統(如 X Window、MS Windows)是採用事件驅動(event-driven)的模式。視窗系統必須處理許多不同的事件(event)— 如:鍵盤輸入、滑鼠移動、壓下滑鼠按鍵、放開滑鼠按鍵等等使用者的動作,以及視窗遮蓋、視窗浮現等等螢幕狀態的改變。這些事件依序地擺放在所謂的事件佇列(event queue)中,然後用循覆的方式依序處理(稱為事件迴路(event loop))。我們以下圖說明之:
front rear 加入新事件 event queue 取出下一個事件 event loop 判斷是何事件 呼叫該事件的 處理函式
GLUT callback 函式 • GLUT 利用 callback 函式的機制來註冊事件處理函式。GLUT 提供了一些函式來設定事件處理函式。 • glutDisplayFunc (void (*func)(void)) • 設定 func為處理視窗內容變動事件的函式。我們必須把所有繪製視窗內容的程式碼寫在函式 func之中。
glutReshapeFunc (void (*func)(intw, inth)) • 設定 func為處理視窗大小變動事件的函式。參數 w和 h是視窗的新寬度與新高度。 • glutKeyboardFunc (void (*func)(unsigned char key, intx, inty)) • 設定 func為處理鍵盤事件的函式。參數 key是按鍵的 ASCII 碼,參數 (x, y) 是按鍵時滑鼠所在的座標。 • glutMouseFunc (void (*func)(intbutton, intx, inty)) • 設定 func為處理滑鼠按鍵事件的函式。參數 button是所按下或放開的滑鼠鍵,參數 (x, y) 是按鍵時滑鼠所在的座標。
glutMotionFunc (void (*func)(intx, inty)) • 設定 func為處理按住滑鼠鍵並移動滑鼠事件的函式。參數 x和 y是滑鼠目前所在的座標。 • glutPassiveMotionFunc (void (*func)(intx, inty)) • 設定 func為處理滑鼠移動事件(未按下滑鼠鍵)的函式。參數 x和 y是滑鼠目前所在的座標。 • glutIdleFunc (void (*func)(void)) • 設定 func為處理「空事件(即無任何事件發生)」的函式。
glutTimerFunc (insignedintmsec, void (*func)(intvalue ), intvalue ) • 設定 func為處理定時器事件的函式。參數 msec是啟動定時器的間隔時間,其單位是毫秒(千分之一秒)。系統會每隔 msec毫秒自動呼叫函式 func,並以glutTimerFunc第三個參數 value的值為其參數值。
void glutMainLoop (void) 在程式中你應該只呼叫glutMainLoop函式一次來進入事件迴圈。這個函式的責任是不斷地檢驗事件的種類,然後呼叫你所指定的事件處理 callback 函式。此外,這個函式本身是一個無限迴圈,無法結束執行而回到主函式。
Create a vertex array object GLuintvao; glGenVertexArrays( 1, &vao ); glBindVertexArray( vao );
Create and initialize a buffer object // vec2 points[NumPoints]; GLuintbuffer; glGenBuffers( 1, &buffer ); glBindBuffer( GL_ARRAY_BUFFER, buffer ); glBufferData( GL_ARRAY_BUFFER, sizeof(points),points, GL_STATIC_DRAW ); points Host GPU buffer
Load and use shader programs GLuint program = InitShader( "vshader21.glsl", "fshader21.glsl" ); glUseProgram( program );
Vertex Shader (vshader21.glsl) #version 150 in vec4 vPosition; void main() { gl_Position = vPosition; }
Fragment Shader (fshader21.glsl) #version 150 out vec4 fColor; void main () { fColor = vec4(1.0, 0.0, 0.0, 1.0); }
Initialize vertex position attribute // Defined in Angel.h // #define BUFFER_OFFSET(offset) ((GLvoid*) (offset)) GLuintloc = glGetAttribLocation( program, "vPosition" ); glEnableVertexAttribArray( loc ); glVertexAttribPointer( loc, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) ); GPU buffer
Display // in init() // glClearColor( 1.0, 1.0, 1.0, 1.0 ); // white background void display( void ) { glClear( GL_COLOR_BUFFER_BIT ); // clear the window glDrawArrays( GL_POINTS, 0, NumPoints ); // draw the points glFlush(); }
清除視窗的內容 • glClearColor (GLclampfred, GLclampfgreen, GLclampfblue, GLclampfalpha) • 設定清除的顏色。各顏色的成份值必須介於 0.0 和 1.0 之間。值愈小表示成份愈少。所以 (0.0, 0.0, 0.0, 0.0) 代表黑色、 (1.0, 1.0, 1.0, 0.0) 代表白色、 (1.0, 0.0, 0.0, 0.0)代表紅色、…、等等。第四個參數 alpha用來設定透明度。
glClear (GLbitfield mask) • 用目前的清除值來清除參數 mask所選定的緩衝區。以下的緩衝區可以用 bitwise OR 的方式來選取: • GL_COLOR_BUFFER_BIT (glClearColor) • GL_DEPTH_BUFFER_BIT (glClearDepth) • GL_ACCUM_BUFFER_BIT (glClearAccum) • GL_STENCIL_BUFFER_BIT (glClearStencil) • 註:不同的緩衝區需要用不同的函式(上表的右方)來設定清除值。
範例: • glClearColor(0.0, 0.0, 0.0, 0.0); • glClearDepth(1.0); • glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glFlush() 和 glFinish() glFlush() 函式和 glFinish() 函式都會要求立刻執行之前所下達的 OpenGL 指令。兩者不同的地方在於: glFlush() 要求後就結束函式的執行,而 glFinish() 必須等到這些指令都完成後,才會結束函式的執行。 透過網路來執行的 OpenGL 程式可以運用這兩個函式來增進執行的效率。