opengl超級寶典筆記—Using OpenGL(三)

<p><b>OpenGL狀態機<br></b> <p>&nbsp;&nbsp;&nbsp;&nbsp; 繪製3D圖形是一項複雜的任務。咱們須要許多的屬性,好比光照屬性,材料屬性,紋理等。若是咱們在每次繪製圖形的時候,都去設置這些屬性,或者以參數的形式傳進去。那工做量很是大,並且還易出錯。因此OpenGL使用了狀態模式,來管理這些屬性,使得圖形編程變得更簡潔,容易。 <p>&nbsp;&nbsp;&nbsp;&nbsp; 光照屬性,材料屬性等等屬性變量的集合就是管線的狀態。狀態機是一系列狀態變量的集合的抽象模型。每一個狀態變量能夠有不一樣的值,例如打開或關閉等。 <p>打開狀態可使用: <p>void glEnable(GLenum capability); <p>關閉狀態可使用 <p>void glDisable(GLenum capability); <p>例子: <p>打開光照 <p>glEnable(GL_LIGHTING); <p>關閉光照 <p>glDisable(GL_LIGHTING); <p>Opengl還提供了檢查這些狀態的方法: <p>GLboolean glIsEnabled(GLenum capability); <p>不是全部的狀態變量只有簡單的打開或關閉的狀態。許多OpenGL的函數設置這些狀態值一直到被改變爲止。你能夠隨時查找這些狀態變量的值。OpenGL提供了各類類型的超找函數。 <p>void glGetBooleanv(GLenum pname, GLboolean *params); <p>void glGetDoublev(GLenum panme, GLdouble *params); <p>void glGetFloatv(GLenum pname, GLfloat *params); <p>void glGetIntegerv(GLenum pname, GLint *params); <p>每個函數返回一個值或者一個值數組,存儲在你提供的參數params中。 <p><b>保存和恢復狀態</b> <p>OpenGL提供了保存和恢復狀態的方法。是使用棧(後進先出LIFO)的方式來保存這些變量的。 <p>兩個OpenGL的命令以下: <p>保存狀態 void glPushAttrib(GLbitfield mask); <p>恢復狀態 void glPopAttrib(GLbitfield mask); <p>參數是使用位段的方式來保存狀態。這就意味着你能夠在單個函數調用中用位OR操做來表示多個狀態。 <p>例如: <p>glPushAttrib(GL_TEXTURE_BIT|GL_LIGHTING_BIT); <p>獲取時: <p>glPopAttrib(mask); <p>if (mask &amp; GL_LIGHTING_BIT == GL_LIGHTING_BIT)&nbsp; glEnable(GL_LIGHTING); <p><b>OpenGL的錯誤處理</b> <p>OpenGL在內部維護了一組錯誤標誌,每一個標誌表明一種不一樣類型的錯誤。當一個錯誤發生時,與這個錯誤相對應的標誌會被設置。咱們能夠調用glGetError(void)來檢查這些標誌。 <p>GLenum glGetError(void); <p>glGetError會返回一個錯誤值。若是被設置的錯誤值不止一個,glGetError仍然只返回一個值。須要遍歷不斷去取值,持續檢查錯誤值,直到返回GL_NO_ERROR。 <p>錯誤代碼<br>描述 <p>GL_INVALID_ENUM<br>枚舉值超出函數範圍 <p>GL_INVALID_VALUE<br>數值參數超出範圍 <p>GL_INVALID_OPERATION<br>在當前的狀態下操做非法 <p>GL_STACK_OVERFLOW<br>堆棧上溢 <p>GL_STACK_UNDERFLOW<br>堆棧下溢 <p>GL_OUT_OF_MEMORY<br>沒有足夠的內存來執行這條命令 <p>GL_TABLE_TOO_LARGE<br>指定的表太大 <p>GL_NO_ERROR<br>沒有出現錯誤 <p>咱們可使用GLU函數庫的另外一個函數gluErrorString來得到一個錯誤標誌的字符串描述 <p>const GLubyte* gluErrorString(GLenum errorCode); <p>這個函數將錯誤標誌做爲它的惟一參數,並返回一個描述這個錯誤的靜態字符串。 <p>例子: 若是當前的錯誤標誌位GL_INVALID_ENUM,則 <p>gluErrorString(glGetError()); 將返回 <p>invalid enumerant&nbsp; <p><b>獲取版本</b> <p>有時候咱們但願利用一個特定環境所提供的特定功能。咱們須要針對不一樣的環境進行編程的話,咱們須要知道OpenGL驅動程序的生產商和版本號。能夠調用glGetString <p>const GLubyte* glGetString(GLenum name); <p>這個函數返回一個靜態的字符串,描述了GL函數庫的相關信息。 <p>GLU函數庫提供了另外一個對應的函數gluGetString. <p>const GLubyte *gluGetString(GLenum name); <p>這個函數返回一個字符串,描述它所請求的GLU函數的相關信息。 <p><b>glHint</b> <p>有時咱們須要在性能和渲染效果中進行選擇,而glHint能給OpenGL提供一個啓示,你更關注渲染效果仍是性能。 <p>glHint容許指定偏重與視覺仍是性能,函數原型以下: <p>void glHint(GLenum target, GLenum mode); <p>target指定行爲類型。mode參數則告訴OpenGL咱們最爲關心的部分。這是惟一一個徹底依賴於生產商的實現的函數。 <p><b>檢查擴展</b> <p>OpenGL容許廠商進行擴展。要檢查一個驅動程序包含了哪些擴展。以下: <p>const char *szExtensions = glGetString(GL_EXTENTIONS); <p>這個字符串包含了驅動程序支持的全部擴展名稱(用空格分隔)。查找但願使用的擴展: <p>if(strstr(extensions, "WGL_EXT_swap_control")&nbsp; != NULL)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp; wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");<br>&nbsp;&nbsp;&nbsp;&nbsp; if (wglSwapIntervalEXT != NULL)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wglSwapIntervalEXT(1);<br>} <p>使用這種方法,還應該確保擴展後面的那個字符串是空格或NULL,不然若是這個擴展被WGL_EXT_swap_control2所取代。此時C運行時函數strstr仍然找到第一個字符串,可是咱們沒法肯定第二個的行爲和第一個是否相同。 <p><b>OpenGL的擴展前綴</b><b> </b></p> <table border="2" cellspacing="0" cellpadding="2" width="600"> <tbody> <tr> <td valign="top" width="300">前綴</td> <td valign="top" width="300">廠商</td></tr> <tr> <td valign="top" width="300">SGI_</td> <td valign="top" width="300">silicon Graphics</td></tr> <tr> <td valign="top" width="300">IBM_</td> <td valign="top" width="300">IBM</td></tr> <tr> <td valign="top" width="300">WGL_</td> <td valign="top" width="300">MicroSoft</td></tr> <tr> <td valign="top" width="300">NV_</td> <td valign="top" width="300">NVida</td></tr> <tr> <td valign="top" width="300">ATI_</td> <td valign="top" width="300">ATI</td></tr> <tr> <td valign="top" width="300">EXT_</td> <td valign="top" width="300">跨廠商</td></tr> <tr> <td valign="top" width="300">ARB_</td> <td valign="top" width="300">ARB標準</td></tr></tbody></table> <p>NVida的擴展獲得了普遍的使用,ATI也支持了NVida的擴展。</p> <p>ARB批准的擴展,是經過OpenGL ARB的審查的擴展。</p>編程

相關文章
相關標籤/搜索