OpenGL版本與OpenGL擴充套件機制(轉)

weixin_34321977發表於2010-04-28
 

OpenGL版本比較
1 opengl的版本區別(在opengl官方文件中有詳細說明)
針對Opengl不同版本的升級是主要是擴充套件指令集。
1.1 opengl1.1
1995年,SGI推出了更為完善的OpenGL 1.1版本。OpenGL 1.1的效能比1.0版提高甚多。其中包括改進印表機支援,在增強元檔案中包含OpenGL的呼叫,頂點陣列的新特性,提高頂點位置、法線、顏色、色彩指數、紋理座標、多邊形邊緣標識的傳輸速度,引入了新的紋理特性等等。
1.2 opengl1.3
2001年8月,ARB釋出OpenGL 1.3規範,它增加了立方紋理貼圖、紋理環境、多重取樣、紋理框架壓縮等擴充套件指令,但是改程式度非常有限。
1.3 opengl1.4
2002年7月,ARB正式釋出OpenGL 1.4,它也只加入了深度紋理/陰影紋理、頂點設計框架、自動紋理貼圖等簡單的功能。
1.3 opengl1.5
2003年的7月,ARB公佈OpenGL 1.5規範。OpenGL 1.5內包含ARB制定的“正式擴充套件規格繪製語言”(OpenGL Shading Language v1.0),該語言用於著色物件、頂點著色、片斷著色等擴充套件功能,同時也將作為下一代OpenGL 2.0版本的核心。OpenGL 1.5的變化還增加了頂點緩衝物件(可提高透視效能)、非乘方紋理(可提高紋理記憶體的使用效率)以及陰影功能、隱蔽查詢功能等等。其主要內容包括
l 頂點Buffer Object:進行頂點配列方式可以提高透視效能
l Shadow功能:增加用來比較Shadow對映的函式
l 隱蔽查詢(QUERY):為提高Curling效能採用非同步隱蔽測試
l 非乘方紋理(Texture):提高mipmap等紋理記憶體的使用效率
l OpenGL Shading Language v.1.0:用於著色(shader)物件、頂點著色以及片斷著色技術(fragment shader )的擴充套件功能
1.4 opengl2.0
OpenGL 1.0推出後的相當長的一段時間裡,OpenGL唯一做的只是增加了一些擴充套件指令集,這些擴充套件指令是一些繪圖功能,像是ClearCoat、Multisample、視訊及繪圖的整合工具(某些是通過OpenML的努力而開發出來的,它本身屬於OpenGL ARB擴充套件指令之一。
去年8月已經推出opengl2.0。OpenGL 2.0將在OpenGL 1.3基礎上進行修改擴充、但它將有下面五個方面的重大改進:①複雜的核心被徹底精簡;②完全的硬體可程式設計能力;③改進的記憶體管理機制、支援高階畫素處理;④擴充套件至數字媒體領域,使之跨越高階圖形和多媒體範疇;⑤支援嵌入式圖形應用。
為了在獲得強大功能的同時保持理想的相容性,OpenGL 2.0經歷以下兩個發展階段:第一個階段注重相容能力和平滑過渡,為此,OpenGL 2.0核心將在精簡後的OpenGL 1.3功能模組的基礎上加上可完全相容的新功能共同組成,這種做法在滿足相容性的同時,還可將原有OpenGL中數量眾多、且相互糾纏不清的擴充套件指令進行徹底精簡。 第一階段的任務只是為了過渡,而第二階段才是OpenGL 2.0的真正成熟期。此時,ARB將合成出一個“純OpenGL 2.0”核心,純核心將包含更多新增加的“精簡型API函式”,這些函式具有完全的可程式設計特性、結構簡單高效、功能強大且應用靈活。除了完成這項任務外,ARB組織還得指導開發商拋棄繁瑣的OpenGL 1.X、轉用更具彈性的“純OpenGL 2.0”。
2 OpenGL擴充套件(OpenGL Extensions)
OpenGL和Direct3D比較起來,最大的一個長處就是其擴充套件機制。硬體廠商開發出一個新功能,可以針對新功能開發OpenGL擴充套件,軟體開發人員通過這個擴充套件就可以使用新的硬體功能。所以雖然顯示卡的發展速度比OpenGL版本更新速度快得多,但程式設計師仍然可以通過OpenGL使用最新的硬體功能。而Direct3D則沒有擴充套件機制,硬體的新功能要等到微軟釋出新版DirectX後才可能支援。
OpenGL擴充套件也不是沒有缺點,正因為各個硬體廠商都可以開發自己的擴充套件,所以擴充套件的數目比較大,而且有點混亂,有些擴充套件實現的相同的功能,可因為是不同廠商開發的,介面卻不一樣,所以程式中為了實現這個功能,往往要為不同的顯示卡寫不同的程式。這個問題在OpenGL 2.0出來後可能會得到解決,OpenGL 2.0的一個目標就是統一擴充套件,減少擴充套件數目。
2.1 副檔名
每個擴充套件都有一個副檔名,副檔名類似如下形式:
GL_ARB_multitexture
第一段GL,用來表示針對OpenGL哪部分開發的擴充套件,有以下幾個值:
GL – 針對OpenGL核心的擴充套件
WGL – 針對Windows平臺的擴充套件
GLX – 針對Unix / Linux平臺的擴充套件
GLU – 針對OpenGL Utility Library的擴充套件
第二段ARB,用來表示是誰開發的這個擴充套件,常見以下幾個值:
ARB – 經OpenGL Architecture Review Board(OpenGL管理機構)正式核准的擴充套件,往往由廠商開發的擴充套件發展而來,如果同時存在廠商開發的擴充套件和ARB擴充套件,應該優先使用ARB擴充套件
EXT – 被多個硬體廠商支援的擴充套件
NV – nVIDIA 公司開發的擴充套件
ATI – ATI公司開發的擴充套件
ATIX– ATI公司開發的實驗性擴充套件
SGI – Silicon Graphics(SGI)公司開發的擴充套件
SGIX– Silicon Graphics(SGI)公司開發的實驗性擴充套件
第三段multitexture就是真正的副檔名了,如multitexture就是多重紋理擴充套件。
2.2使用OpenGL擴充套件
要使用一個OpenGL擴充套件,首先必須檢查顯示卡是否支援這個擴充套件,以下程式碼可以獲取一個顯示卡支援的的OpenGL擴充套件:
const char *str = glGetString( GL_EXTENSIONS );
函式返回一個字串指標,這個字串就是顯示卡所支援的所有擴充套件的副檔名,不同的副檔名之間用空格隔開,形如:
"GL_ARB_imaging GL_ARB_multitexture GL_ARB_point_parameters ……"
OpenGL擴充套件往往都會新增一些函式,在Windows平臺上,這些函式不是通過.lib庫連線到程式裡的,而要在執行時動態獲得函式的指標。我們以GL_ARB_point_parameters擴充套件為例看看怎麼獲得函式指標。
首先要定義函式指標型別,
typedef void (APIENTRY * PFNGLPOINTPARAMETERFARBPROC)(GLenum pname,
GLfloat param);
typedef void (APIENTRY * PFNGLPOINTPARAMETERFVARBPROC)(GLenum pname,
const GLfloat *params);
這個工作SGI已經為我們做好,它提供了一個標頭檔案 glext.h ,裡面有目前絕大多數擴充套件的常量和函式指標定義,下載下來放到編譯器的include/GL資料夾下面,然後在程式裡面加上:
#include <GL/glext.h>
就可以在程式中使用常量和函式指標型別了。
然後要定義函式指標:
PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB;
PFNGLPOINTPARAMETERFVARBPROC glPointParameterfvARB;
再檢查顯示卡是否支援GL_ARB_point_parameters擴充套件,其中isExtensionSupported是自定義的一個函式,就是在glGetString( GL_EXTENSIONS )返回的字串裡查詢是否存在指定的副檔名:
int hasPointParams = isExtensionSupported("GL_ARB_point_parameters");
如果支援,就可以用wglGetProcAddress函式獲取擴充套件函式的指標:
if (hasPointParams)
{
glPointParameterfARB = (PFNGLPOINTPARAMETERFARBPROC)\
wglGetProcAddress( "glPointParameterfEXT" );
glPointParameterfvARB = (PFNGLPOINTPARAMETERFVARBPROC) \
wglGetProcAddress( "glPointParameterfvEXT" );
}
最後就可以在程式裡使用擴充套件函式:
if (hasPointParams)
{
static GLfloat quadratic[3] = { 0.25, 0.0, 1/60.0 };
glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, quadratic);
glPointParameterfARB(GL_POINT_FADE_THRESHOLD_SIZE_ARB, 1.0);
}
另外,下面程式碼說明如何訪問擴充套件函式:(資料來源於csdn知識庫)
呼叫wglGetProcAddress函式訪問一個不在標準OpenGL庫中的擴充套件函式。如果該擴充套件函式存在當前的執行(implementation)中,那麼wglGetProcAddress返回一個用來訪問該函式的函式指標。否則,wglGetProcAddress返回NULL.
例如,要訪問glAddSwapHintRectWIN擴充套件函式,如下呼叫wglGetProcAddress:
// Get a pointer to the extension function.
typedef void (WINAPI *FNSWAPHINT)(GLint, GLint, GLsizei, GLsizei);
fnSwapHint = (FNSWAPHINT)wglGetProcAddress("glAddSwapHintRectWIN");
// Actual call to glAddSwapHintRectWIN.
if (fnSwapHint != NULL)
(*fnSwapHint)(0, 0, 100, 100);
2.3 WGL擴充套件
glGetString( GL_EXTENSIONS )取得的擴充套件字串中並不包括針對Windows平臺的WGL擴充套件,WGL擴充套件串要通過WGL_ARB_extensions_string擴充套件來獲得,以下程式碼演示瞭如何獲得WGL擴充套件串:
定義WGL_ARB_extensions_string擴充套件新增函式wglGetExtensionsStringARB的函式指標型別,同樣這個工作SGI已經為我們做好,只不過不在glext.h中,而在它提供的另外一個標頭檔案 wglext.h 中:
typedef const char *(APIENTRY * PFNWGLGETEXTENSIONSSTRINGARBPROC)(
HDC hdc);
定義函式指標:
PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB;
檢查是否支援WGL_ARB_extensions_string擴充套件,如果不支援,表示這個顯示卡不支援WGL擴充套件,如果支援,則得到wglGetExtensionsStringARB函式的指標,並呼叫它得到WGL擴充套件串:
int hasWGLext = isExtensionSupported("WGL_ARB_extensions_string");
if (hasWGLext)
{
wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) \
wglGetProcAddress( "wglGetExtensionsStringARB" );
const char *wglExt = wglGetExtensionsStringARB( hdc );
……
}
2.4 OpenGL版本
一些常用的OpenGL擴充套件會在新版的OpenGL中加到OpenGL核心中去,成為OpenGL標準的一部分,可以簡化程式開發,程式設計師使用這些功能時不必做繁瑣的擴充套件初始化工作。比如多重紋理功能,在OpenGL1.2.1加入到OpenGL核心中,以前要使用多重紋理,要先檢查是否支援GL_ARB_multitexture擴充套件,然後初始化glActiveTextureARB等函式,很麻煩,而OpenGL1.2後,則可以直接使用glActiveTexture函式。
不過,這種簡化只有Mac/Unix/Linux程式設計師才能享受到,在Windows平臺上沒有這麼簡單。微軟為了維護Direct3D,對OpenGL的支援很消極,其OpenGL實現仍然是1.1。由於Windows上的OpenGL程式最終都會動態連結到微軟的OpenGL32.dll,可OpenGL32.dll只支援OpenGL 1.1,使我們不能直接使用新版OpenGL,仍然要用擴充套件訪問OpenGL1.1以來新增的功能。
2.5 OpenGL擴充套件資料
All About OpenGL Extensions :必讀。
討論OpenGL擴充套件機制,講述瞭如何閱讀擴充套件官方說明書,並舉了一些擴充套件的例子。
OpenGL Extension Registry :
由SGI維護,列出了目前公開的所有擴充套件及其官方說明書。
OpenGL Hardware Registry : 由Delphi3D.net維護,列出了目前幾乎所有3D加速卡的OpenGL硬體資訊,包括其支援的擴充套件。當然,這裡面列的擴充套件不能作為程式的依據,程式中要使用某個擴充套件,還是要先檢查顯示卡是否支援。因為同樣的顯示卡,如果驅動程式不同,支援的擴充套件也不相同,往往新的驅動程式會加入新的擴充套件,丟掉一些廢棄的擴充套件。
2.6 OpenGL硬體加速
在Windows平臺上,OpenGL驅動可能有三種模式:純軟體、MCD和ICD:
純軟體模式:微軟提供一個OpenGL的軟體實現,所有渲染操作均由CPU完成,速度很慢。如果安裝系統時使用Windows自帶的顯示卡驅動程式,那麼OpenGL程式就會執行在軟體模式下。而且由於微軟有自己的Direct3D,所以對OpenGL的支援很消極,它的OpenGL純軟體實現只支援OpenGL1.1,而目前OpenGL的最新版本為1.4
MCD(Mini Client Driver):MCD是早期微軟在Windows NT上支援OpenGL時,為了簡化驅動開發時使用的一個模型。在這個模型中,OpenGL渲染管線的變換、光照部分仍然由軟體實現,而光柵化部分則由硬體廠商實現,因此只要硬體支援,MCD可以硬體加速光柵化部分。MCD雖然可以簡化驅動開發,但是功能限制太大,現在市面上的3D加速卡均支援硬體變換和光照,MCD卻不能利用這一特性,看上去MCD已經沒有存在的價值
ICD(Installable Client Driver):ICD是一個完整的OpenGL驅動模型,比MCD複雜得多。硬體廠商要實現完整的OpenGL渲染管線,如變換、光照、光柵化等,因此只要硬體支援,ICD可以硬體加速整個OpenGL渲染管線。我們通常說的OpenGL硬體加速就是指的通過ICD模型獲得的硬體加速,而現在硬體廠商提供的OpenGL驅動程式也都是依照ICD模型開發的。主要硬體廠商的ICD已經可以支援OpenGL的最新版1.4
Windows怎麼實現OpenGL硬體加速呢?OpenGL32.dll是微軟的OpenGL 1.1純軟體實現,我們的程式都要動態連結到這個dll。如果安裝3D晶片廠商的驅動程式,會將一個不同名字的dll放到Windows系統目錄下,比如在Windows 2000下安裝nVIDIA GeForce2 MX的驅動程式,會在系統目錄下放一個nvoglnt.dll(這就是nVIDIA的OpenGL驅動),並在登錄檔中登記nvoglnt.dll,讓Windows知道硬體加速OpenGL驅動的名字,以後執行OpenGL程式,OpenGL32.dll就會把OpenGL呼叫直接轉到nvoglnt.dll。
Windows平臺上,一個OpenGL程式是否使用硬體加速由三個因素決定,這三個因素缺一不可,否則程式都會執行於純軟體模式:
是否有一塊3D加速卡
是否安裝了顯示卡廠商提供的最新的驅動程式,Windows自帶的顯示卡驅動程式並不會提供OpenGL硬體加速能力
指定的畫素格式是否被顯示卡硬體所支援
判斷一種畫素格式是否被顯示卡硬體所支援,可以用函式DescribePixelFormat取得該畫素格式的資料,然後看結構體PIXELFORMATDESCRIPTOR中的dwFlags的值,如果
PFD_GENERIC_FORMAT被置1,並且PFD_GENERIC_ACCELERATED被置0,即
(pfd.dwFlags & PFD_GENERIC_FORMAT) &&
!(pfd.dwFlags & PFD_GENERIC_ACCELERATED)
表明該畫素格式不被顯示卡硬體支援,使用該畫素格式的OpenGL程式將使用純軟體模式渲染
PFD_GENERIC_FORMAT被置1,並且PFD_GENERIC_ACCELERATED被置1,即
(pfd.dwFlags & PFD_GENERIC_FORMAT) &&
(pfd.dwFlags & PFD_GENERIC_ACCELERATED)
表明該畫素格式被顯示卡硬體支援,並且程式使用MCD模式渲染
PFD_GENERIC_FORMAT被置0,並且PFD_GENERIC_ACCELERATED被置0,
!(pfd.dwFlags & PFD_GENERIC_FORMAT) &&
!(pfd.dwFlags & PFD_GENERIC_ACCELERATED)
表明該畫素格式被顯示卡硬體支援,並且程式使用ICD模式渲染
3 OpenGL Extension
這個軟體可以自動測試顯示卡對OpenGL的版本支援和擴充套件命令。

相關文章