OpenGL 入門2

原帖地址:http://ogldev.atspace.co.uk/www/tutorial02/tutorial02.html
http://blog.csdn.net/cordova/article/details/5249176
http://ogldev.atspace.co.uk/www/tutorial03/tutorial03.html
http://blog.csdn.net/cordova/article/details/52494549

OpenGL 中的頂點

glew

我們將會使用一個叫glew的庫,這個庫會幫助我們更輕鬆的管理opengl擴展。每當glew被初始化之後,它就會動態的加載當前系統中可用的opengl擴展,並且通過一個簡單的頭文件來提供快捷方便的訪問。

VBO

VBO(vertex buffer object),顧名思義,這是一個用於存儲頂點信息的緩存。所有3D世界中的怪物,建築等都是由一個一個的頂點連接起來組成的。VBO是將頂點信息傳給GPU的最快的方式,因爲VBO是可以存在於顯卡緩存上的。

API

GLenum glewInit();

用於初始化glew,如果初始化失敗GLenum的值就不會是GLEW_OK。

GLfloat vertices[3][3] = {{0.0,1.0,0.0},
                          {-1.0,0.0,0.0},
                          {1.0,0.0,0.0}};

初始化我們需要用到的頂點。

GLuint vbo;
glGenBuffer(1,&vbo);

opengl定義了很多中glGen*類型的函數用於分配不同類型的句柄。第一個參數標明分配的句柄的數量,第二個參數是一個數組的地址,數組中存儲的是句柄。如果一個句柄沒有被glDeleteBuffers函數刪除,那麼opengl就不會分配一個相同的句柄出來。在這裏我們只是分配了句柄,相當於c語言中的指針。在這個句柄沒有綁定具體的對象之前是不能使用的,就相當於c語言中的空指針,我們不能使用它來進行函數調用。

glBindBuffer(GL_ARRAY_BUFFER,vbo);

OpenGL有一種與衆不同的使用句柄的技巧。在其他的API中,句柄通常被用做一個參數在各個相關的函數之間傳遞,並且通常會對這個句柄做一些處理。在OpenGL中,我們會將多個句柄綁定到一個target上,然後通過在target上執行命令來影響綁定到target上的句柄。當我們想要解除這種綁定關係可以用另外的句柄來替換當前綁定的句柄,又或者是將以上參數的句柄設置爲0。GL_ARRAY_BUFFER意味這我們將這個叫做vbo的句柄,指向了一個緩存。另一個有用的target是GL_ELEMENT_ARRAY_BUFFER意味着vbo指向的是一個索引緩存。當我們第一次綁定對象的時候,OpenGL內部會分配這個對象所需的內存並且將它作爲當前對象,即所有後繼的操作都會作用於這個被綁定的對象。一般說來有兩種情況我們需要綁定對象,一是創建對象並初始化它所對應的數據時;二是每次我們準備使用這個對象,而它並不是當前綁定的對象時。

glDeleteBuffer(vbo);
glBindBuffer(0);

既然有綁定,那麼就有解綁。解綁有兩種方式,glDeleteBuffer()和glBindBuffer()。前者將當前vbo置爲0且將vbo所指向的對象也清楚,後者只是將當前綁定對象的vbo置爲0,但此vbo指向的對象依然在,且編程默認渲染狀態。

glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);

這個函數的作用是向我們的緩存裏面加載頂點數據。第一個參數是我們的頂點緩存,第二個參數是傳入的頂點信息的大小,第三個參數是傳入的頂點信息的起始地址,第四個參數表明我們不會改變頂點緩存中的內容,與之對應的則是GL_DYNAMIC_DRAW。

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

這個函數的功能是設定我們如何從buffer裏面挑出我們需要的數據送入shader中。第一個參數是一個索引,這個索引與shader中layout所使用的索引一一對應。此例中,shader中layout對應的索引是location = 0,所以我們這裏的索引值是0。第二個和第三個參數代表我們傳入的數據是怎麼構成的,在這裏我們傳入的數據是位置信息,而位置信息由3個float類型的數據組成。第四個參數設置我們傳入的數據是否進行歸一化。第五個參數設置我們傳入的數據之間的間隔,第六個參數設置傳入的數據開始時的地址,我們是從buffer的最開始傳入數據的,所以設置爲0。
假如我們傳入的數據包括3個float的位置信息以及3個float的法線信息。那這些數據vertex buffer中的存在方式就像下圖:
這裏寫圖片描述
那麼我們第五個參數應該設置爲12,因爲位置信息之間隔了3個float類型的法線信息,而一個float是4個字節,那麼三個float就是12個字節。

glEnableVertexAttribArray(0);

在設置完傳入的數據之後,我們要讓與這個索引相關聯的頂點數組能夠被shader使用,這個時候就需要使用這個函數,傳入的參數,就是這個將要在shader中被使用的且設置好的索引。

glDrawArrays(GL_POINTS, 0, 1);

這個函數的作用是設定用哪些頂點畫出那種圖元。第一個參數設定圖元,第二個參數設定起始頂點索引值,第三個參數設定使用的頂點數量。

glDisableVertexAttribArray(0);

當渲染完成之後,記得把頂點屬性數組重置一下。因爲當沒有shader使用某個屬性時依然保留AttibPointer感覺怪怪的。

查看當前的opengl版本

    const GLubyte* name = glGetString(GL_VENDOR); //返回負責當前OpenGL實現廠商的名字
    const GLubyte* biaoshifu = glGetString(GL_RENDERER); //返回一個渲染器標識符,通常是個硬件平臺
    const GLubyte* OpenGLVersion =glGetString(GL_VERSION); //返回當前OpenGL實現的版本號
    const GLubyte* gluVersion= gluGetString(GLU_VERSION); //返回當前GLU工具庫版本
    printf("OpenGL實現廠商的名字:%s\n", name);
    printf("渲染器標識符:%s\n", biaoshifu);
    printf("OpenGL實現的版本號:%s\n",OpenGLVersion );
    printf("OGLU工具庫版本:%s\n", gluVersion);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章