OpenGL狀態機
繪制3D圖形是一項復雜的任務。我們需要許多的屬性,比如光照屬性,材料屬性,紋理等。如果我們在每次繪制圖形的時候,都去設置這些屬性,或者以參數的形式傳進去。那工作量非常大,而且還易出錯。所以OpenGL使用了狀態模式,來管理這些屬性,使得圖形編程變得更簡潔,容易。
光照屬性,材料屬性等等屬性變量的集合就是管線的狀態。狀態機是一系列狀態變量的集合的抽象模型。每個狀態變量可以有不同的值,例如打開或關閉等。
打開狀態可以使用:
void glEnable(GLenum capability);
關閉狀態可以使用
void glDisable(GLenum capability);
例子:
打開光照
glEnable(GL_LIGHTING);
關閉光照
glDisable(GL_LIGHTING);
Opengl還提供了檢查這些狀態的方法:
GLboolean glIsEnabled(GLenum capability);
不是所有的狀態變量只有簡單的打開或關閉的狀態。許多OpenGL的函數設置這些狀態值一直到被改變為止。你可以隨時查找這些狀態變量的值。OpenGL提供了各種類型的超找函數。
void glGetBooleanv(GLenum pname, GLboolean params);
void glGetDoublev(GLenum panme, GLdouble params);
void glGetFloatv(GLenum pname, GLfloat params);
void glGetIntegerv(GLenum pname, GLint params);
每一個函數返回一個值或者一個值數組,存儲在你提供的參數params中。
保存和恢復狀態
OpenGL提供了保存和恢復狀態的方法。是使用棧(後進先出LIFO)的方式來保存這些變量的。
兩個OpenGL的命令如下:
保存狀態 void glPushAttrib(GLbitfield mask);
恢復狀態 void glPopAttrib(GLbitfield mask);
參數是使用位段的方式來保存狀態。這就意味著你可以在單個函數調用中用位OR操作來表示多個狀態。
例如:
glPushAttrib(GL_TEXTURE_BIT|GL_LIGHTING_BIT);
獲取時:
glPopAttrib(mask);
if (mask & GL_LIGHTING_BIT == GL_LIGHTING_BIT) glEnable(GL_LIGHTING);
OpenGL的錯誤處理
OpenGL在內部維護了一組錯誤標志,每個標志代表一種不同類型的錯誤。當一個錯誤發生時,與這個錯誤相對應的標志會被設置。我們可以調用glGetError(void)來檢查這些標志。
GLenum glGetError(void);
glGetError會返回一個錯誤值。如果被設置的錯誤值不止一個,glGetError仍然只返回一個值。需要遍歷不斷去取值,持續檢查錯誤值,直到返回GL_NO_ERROR。
錯誤代碼
描述
GL_INVALID_ENUM
枚舉值超出函數范圍
GL_INVALID_VALUE
數值參數超出范圍
GL_INVALID_OPERATION
在當前的狀態下操作非法
GL_STACK_OVERFLOW
堆棧上溢
GL_STACK_UNDERFLOW
堆棧下溢
GL_OUT_OF_MEMORY
沒有足夠的內存來執行這條命令
GL_TABLE_TOO_LARGE
指定的表太大
GL_NO_ERROR
沒有出現錯誤
我們可以使用GLU函數庫的另一個函數gluErrorString來獲得一個錯誤標志的字符串描述
const GLubyte gluErrorString(GLenum errorCode);
這個函數將錯誤標志作為它的唯一參數,並返回一個描述這個錯誤的靜態字符串。
例子: 如果當前的錯誤標志位GL_INVALID_ENUM,則
gluErrorString(glGetError()); 將返回
invalid enumerant
獲取版本
有時候我們希望利用一個特定環境所提供的特定功能。我們需要針對不同的環境進行編程的話,我們需要知道OpenGL驅動程序的生產商和版本號。可以調用glGetString
const GLubyte glGetString(GLenum name);
這個函數返回一個靜態的字符串,描述了GL函數庫的相關信息。
GLU函數庫提供了另一個對應的函數gluGetString.
const GLubyte gluGetString(GLenum name);
這個函數返回一個字符串,描述它所請求的GLU函數的相關信息。
glHint
有時我們需要在性能和渲染效果中進行選擇,而glHint能給OpenGL提供一個啟示,你更關注渲染效果還是性能。
glHint允許指定偏重與視覺還是性能,函數原型如下:
void glHint(GLenum target, GLenum mode);
target指定行為類型。mode參數則告訴OpenGL我們最為關心的部分。這是唯一一個完全依賴於生產商的實現的函數。
檢查擴展
OpenGL允許廠商進行擴展。要檢查一個驅動程序包含了哪些擴展。如下:
const char szExtensions = glGetString(GL_EXTENTIONS);
這個字符串包含了驅動程序支持的所有擴展名稱(用空格分隔)。查找希望使用的擴展:
if(strstr(extensions, “WGL_EXT_swap_control”) != NULL)
{
wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress(“wglSwapIntervalEXT”);
if (wglSwapIntervalEXT != NULL)
wglSwapIntervalEXT(1);
}
使用這種方法,還應該確保擴展後面的那個字符串是空格或NULL,否則如果這個擴展被WGL_EXT_swap_control2所取代。此時C運行時函數strstr仍然找到第一個字符串,但是我們無法確定第二個的行為和第一個是否相同。
OpenGL的擴展前綴
前綴 廠商 SGI silicon Graphics IBM IBM WGL MicroSoft NV NVida ATI ATI EXT 跨廠商 ARB_ ARB標准NVida的擴展得到了廣泛的使用,ATI也支持了NVida的擴展。
ARB批准的擴展,是通過OpenGL ARB的審查的擴展。
OpenGL超級寶典 第4版 中文版PDF+英文版+源代碼 見 http://www.linuxidc.com/Linux/2013-10/91413.htm
OpenGL編程指南(原書第7版)中文掃描版PDF 下載 http://www.linuxidc.com/Linux/2012-08/67925.htm
OpenGL 渲染篇 http://www.linuxidc.com/Linux/2011-10/45756.htm
Ubuntu 13.04 安裝 OpenGL http://www.linuxidc.com/Linux/2013-05/84815.htm
OpenGL三維球體數據生成與繪制【附源碼】 http://www.linuxidc.com/Linux/2013-04/83235.htm
Ubuntu下OpenGL編程基礎解析 http://www.linuxidc.com/Linux/2013-03/81675.htm
如何在Ubuntu使用eclipse for c++配置OpenGL http://www.linuxidc.com/Linux/2012-11/74191.htm
更多《OpenGL超級寶典學習筆記》相關知識 見 http://www.linuxidc.com/search.aspx?where=nkey&keyword=34581