OpenGL開發基礎知識介紹

來源:互聯網
上載者:User

最近由於手機項目中需要用到OpenGL ES的知識,所以這段時間正在研究OpenGL的相關知識。因為OpenGL ES是OpenGL的剪裁版本,所以我直接從OpenGL入手,然後再去看OpenGL ES就很容易上手。從此篇開始,我將發表一系列文章來逐步深入介紹OpenGL的相關知識,開發我們可以使用VC6.0或.NET。

 

  那麼今天我要介紹的是OpenGL開發之旅基礎知識介紹,這很重要,會讓我們從整體上熟悉OpenGL的工作原理及過程。

   

  1. 保持模式與立即模式:
  通常情況下我們編寫3D圖形時可使用兩種不同的方法:
  一種方法我們稱之為保持模式。在保持模式中,我們可以向編寫的API或是工具箱提供物體及情境的描述,然後圖形包就會在螢幕上建立這個映像,我們需要做的就是提供命令去改變照相機或情境中其他物體的位置和觀察方向。對於我們開發人員而言,我們建立的能夠對物體及情境的描述稱為情境圖,情境圖是什麼呢?大家可能對這個名稱比較熟悉但卻不能說出它的準確含義。在通常情況下,情境圖是個有向非循環圖的資料結構,它包含了情境中的所有物體以及這些物體之間相互的關係,實現了對物體及情境的描述。據瞭解,現在許多的遊戲引擎及高層工具箱都使用了這種方法。這使得我們開發人員不需要對其渲染過程進行特別精細的控制,它只需要向圖形函數庫提供一個模型或是情境,圖形函數庫就會負責進行渲染,大大減輕了我們開發人員的工作量。

 

  另一種方法我們稱之為立即模式。在立即模式中,我們不需要像保持模式一樣去提供一個模型或是情境,而是向圖形處理器發送命令,圖形處理器就會根據它的狀態及發送的命令產生立即的效果。查詢圖形學書籍得知,大多數保持模式中的API或情境圖在其內部使用一個立即模式的API執行實際的渲染任務。

 

  2. OpenGL是什嗎?

  OpenGL是一套API(API),藉助這個API我們開發人員就可以開發出對圖形硬體具有訪問的能力的程式。我們可以使用OpenGL開發出運行效率較高的圖形程式或遊戲,因為OpenGL非常接近底層硬體並且OpenGL使得我們不必去關注圖形硬體的細節。既然我們開發人員不必關注圖形硬體的細節,那麼我們需要關注什麼呢?我們需要關注OpenGL如何繪製,按照專業術語就是根據物體的規格參數及相關屬性,藉助虛擬照相機和光照產生一幅該物體的映像。OpenGL程式與平台是無關的,所以OpenGL API中不包含任何輸入函數或視窗函數,原因是因為這兩種函數都要依賴於特定的平台,例如Windows,Linux或是其他系統。

 

  OpenGL API是過程性的,不是描述性的,即OpenGL不是物件導向的,所以OpenGL無法利用物件導向的特性,例如重載,繼承等,但是我們可以使用物件導向的程式與OpenGL的實現進行連結就可以了。作為開發人員來說,我們不需要去描述情境的性質和外觀,而是去確定一些操作步驟,為些操作步驟是為實現一定圖形或映像所服務的。我們在實現這些步驟時可以調用OpenGL中的一些命令,可以利用這些命令繪製點、直線、多邊形或是其它圖形,還可以調用這些命令實現光照、著色,動畫等各種效果。

 

  OpenGL的實現可以是軟體實現,也可以是硬體實現。軟體實現是對OpengGL函數調用時作出的響應並建立二維或三維映像的函數庫,那麼硬體實現則是通過設定能夠繪製圖形或映像的圖形卡驅動程式。一般來說,硬體實現要比軟體實現快得多。我們都應該熟悉,在Windows上,是由圖形裝置介面將圖形或映像顯示在螢幕上或是其他顯示裝置上的。OpenGL的實現就軟體實現來說,在Windows上會根據程式命令的要求,產生相應的圖形或映像,然後會將這個圖形或映像移交給圖形裝置介面,由圖形裝置介面將圖形或是映像顯示在我們的螢幕上或是其他顯示裝置。這樣一說,我們可能會明白一點OpengGL原來是在應用程式和圖形裝置介面之間運作,但我感覺還不能準確地這樣說。大家看下下面的圖對OpenGL的工作原理可能會理解得更明白一點: 

  

 

  是OpenGL的軟體實現的工作原理。需要注意的是中的構造圖形是通過軟體進行構造的。

 

  OpenGL的硬體實現與軟體實現稍微有些不同,硬體實現是將OpenGL的調用傳遞給硬體驅動程式,而硬體驅動程式不會將產生的圖形或映像傳遞給圖形裝置介面,而是直接與顯示裝置通訊,直接將圖形或映像結果傳遞給顯示器或其他顯示裝置。如所示:

  

  

  OpenGL在繪製圖形時是基於一個被稱為流水線模型的模式。也就是說其中的幾何圖形在程式中通過描述空間位置或頂點來指定其形狀並由程式產生,這些頂點在流經一系列模組時,每個模組在圖形的基本組成部分(在這裡稱為圖元)經過時對其實施一種或多種操作。模組負責對流經的圖元實施一種或多種操作變換,例如:旋轉、平移、縮放及對攝像機進行定位等。

  

  3. OpenGL的組成

  OpenGL中包含許多對圖形影像處理的函數,主要包括以下幾種:

  圖元函數:指定要產生圖形或映像的圖元。主要有兩種類型,一種是繪製二維或三維的幾何圖元,如點,線,多邊形等;另一種是離散型的實體,例如:位元影像。

  屬性函數:屬性函數主要是控製圖元的外觀及樣式,例如:對圖元的顏色、線型、光照及紋理等效果處理。

  觀察函數:觀察函數主要是對攝像機屬性的操作。我們可以操作攝像機顯示圖形或映像近距或是遠距效果。

  控制函數:能夠讓我們啟用或是彬各種OpenGL的特性。

  查詢函數:可以讓我們查詢OpenGL狀態變數的值。

  輸入與視窗控制函數:這個本身不屬於OpenGL,但是由於我們會經常在程式中輸入輸出或是視窗控制操作,所以,這些函數還是比較重要的。

 

  OpenGL函數庫一般包含在兩個庫中,分別稱為GL或GLU。GL是OpenGL的核心庫,包含必需的OpenGL函數。GLU是OpenGL的實用庫,包含許多的新函數。下面的代碼顯示了許多的Windows程式包含的典型標頭檔:

#include <GL/gl.h>#include <GL/glu.h>#include <windows.h>

 

  但是為了實現和視窗系統的互動,一般使用如下代碼引用標頭檔:

#include <GL/glut.h>

 

  GLUT表示OpenGL工具箱,體現了現代視窗系統所共有的功能函數庫。GLUT的目的就是隱藏平台的細節,glut.h已經包含了gl.h和glu.h。使用GLUT是因為OpenGL沒有包含輸入和視窗命令,而輸入和視窗命令是由平台所決定的,與平台的相關性較大。但是前面說過,OpenGL是與平台無關的,也就是說OpenGL是跨平台的。這樣設計人員就需要專門設計一個需要和視窗系統進行互動的函數庫。

 

  為了能使OpenGL代碼更易於從一個平台移植到另一個平台,OpenGL定義了它自己的資料類型,這些資料類型都可以映射到相應的C語言資料類型中。顯示其映射關係:

 

  

  

  4. 開發語言與編程約定

  我們開發OpenGL目前最流行的做法是OpenGL的C語言綁定,當然也可以使用其它平台或語言,例如.NET、JAVA、Python、Perl等。我會在下一篇文章中介紹如何配置相應的環境。

 

  我們以後會見到OpenGL的函數多是以gl開頭,因為OpenGL的函數遵循一定的命名規範,它可以告訴我們這個函數來自哪個函數庫,並且還可以告訴我們這個函數的參數個數和類型。

  OpenGL的函數是採用以下的書寫格式:

  <函數庫首碼><根命令><可選的參數數量><可選的參數類型>

 

  以下是一個函數標註圖:

  

 

  5. 座標系與變換

  在開發OpenGL程式時,需要用到兩個座標系。一個稱為對象座標系,另一個稱為全局座標系。

  第一個座標系是我們在開發中使用的座標系;第二個座標系又稱為視窗座標系或螢幕座標系,在這個座標系中的單位是像素。

  在繪製的過程中,OpenGL會自動實現從對象到視窗座標系的轉換,所需要的資訊是螢幕中顯示視窗的尺寸和使用者希望顯示對象空間的大小。OpenGL中所需要的座標系變換由兩個矩陣決定,即模型視圖矩陣和投影矩陣,這些矩陣是OpenGL的狀態的一部分。設定這兩種矩陣的典型步驟包括以下三個步驟:

  (1) 指定我們希望修改的矩陣。

  (2) 將矩陣設為單位矩陣。

  (3) 修改當前矩陣為使用者期望的矩陣。

 

  以上三個步驟分別對應以下代碼:

glMatrixMode(GL_PROJECTION)glLoadIdentity();gluortho2D(-1.0,1.0,-1.0,1.0)

 

  6. 圖元及屬性

  圖元是圖形系統中常用的基底實體,主要是指:點,線,直線,多邊形,位元影像和像素,我們的2D或3D圖形都可由這幾個基本的圖元來繪製。前面四個稱為幾何圖元,主要是構建幾何圖形;後面二個稱為非幾何圖元。OpenGL在處理幾何圖元和非幾何圖元的方式差別比較大。

  每個圖元都有自己的屬性,屬性決定了由OpenGL顯示的方式。比如多邊形的顏色,形狀,線條的粗細等。

  我們在繪製基本的圖形時,總是以glBegin()函數開始,而以glEnd()函數結束,針對不同的圖形,glBegin()函數中的參數不一樣。如下所示是繪製兩條直線段:

glBegin(GL_LINES);    glVertex2f(-0.5, -0.5);    glVertex2f(-0.5, 0.5);    glVertex2f(0.5, 0.5);    glVertex2f(0.5, -0.5);glEnd();

 

  OpenGL在繪製圖形時有很多功能,比如:光照、消隱、紋理映射等,每一種功能都將影響繪製處理的速度,在我們的程式中可單獨的啟用或是禁用某些功能,在不使用時要將其禁用掉以使我們的程式更加高效。以下是啟用或是禁用某項功能的代碼:

void glEnable(GLenum feature)void glDisable(GLenum feature)//啟用點劃模式glEnable(GL_LINE-STIPPLE)

 

  7. 狀態的儲存

  OpenGL在內部就是一個狀態機器,函數調用會修改其內部的狀態,OpenGL的狀態決定了圖元的行為和繪製方式。我們對圖元的屬性和其他狀態變數所進行的全部修改,例如模型視圖矩陣和投影矩陣,都會改變當前的狀態。在OpenGL中提供了兩種類型的堆棧,可將目前狀態儲存在堆棧中,以便以後使用。

 

  矩陣堆棧可用於儲存投影矩陣和模型視圖矩陣。每種類型的堆棧只能用來容納相應類型的矩陣。所使用的矩陣由當前矩陣模式(GL_MODELVIEW或GL_PROJECTION)所決定的。可用函數glPushMatrix()和glPopMatrix()使矩陣入棧或出棧。

 

  矩陣堆棧的主要作用:一是在構建層次模型時,使用堆棧來遍曆這些層次模型的樹型資料結構;二是在進行繪製時可以回到先前的視圖,而不需要我們重新計算繪製。我們會在開發過程中常看到以下代碼:

glMatrixMode(GL_PROJECTION);glPushMatrix();glPopMatrix();

 

  需要注意的是,入棧操作和出棧操作必須成對使用;一次出棧必須與一次入棧對應。在層次系統中,如果這對操作沒有正確的成對出現的話,將使堆棧處於一種不可預知的狀態。

  

  8. 單緩衝與雙緩衝

  我們在構建圖形視窗時經常也會經常看到以下的一行代碼:

glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); 

 

  這行代碼告訴我們在建立時使用何種類型的顯示模式。GLUT_SINGLE表示使用一個單緩衝的視窗;GLUT_RGBA表示使用RGBA顏色模式。

  單緩衝視窗意味著所有的繪圖命令都是在被顯示的視窗上執行的。另一種顯示模式是雙緩衝視窗,繪圖命令實際上是在一個螢幕之外的緩衝區中執行的,然後快速反應的交換到視窗的視圖上進行顯示。我們經常用雙緩衝模式開發具有動畫效果的程式,這樣會提高我們程式的執行效率。

 

  9. 一個簡單的樣本

  好了,上面說了那麼多,有的人可能想知道OpenGL的程式到底是什麼樣的,主架構是什嗎?大家如果有C語言編程經驗的一眼就能看出來它的結構。

  接下來讓我們看一個運行VC++環境中的OpenGL樣本,代碼如下:

#include "StdAfx.h"#ifdef __APPLE__#include <GLUT/glut.h>#else#include <GL/glut.h>         /* glut.h 包含 gl.h和glu.h*/#endifvoid display(void){    // 清除顏色緩衝區    glClear(GL_COLOR_BUFFER_BIT);     // 繪製矩形    glBegin(GL_POLYGON);         glVertex2f(-0.5, -0.5);         glVertex2f(-0.5, 0.5);         glVertex2f(0.5, 0.5);         glVertex2f(0.5, -0.5);    glEnd();    // 執行緩衝區    glFlush(); }int main(int argc, char** argv){    // 初始化視窗    glutInit(&argc,argv);     glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);      glutInitWindowSize(500,500);    glutInitWindowPosition(0,0);     glutCreateWindow("繪製矩形");     glutDisplayFunc(display);    glutMainLoop();    return 0;}

 

  這是運行在VC6.0中的一個樣本,在建立項目時需要注意建立的是控制台項目。

  怎麼樣?main函數中的代碼你能看懂它的意思嗎?我相信對大家不是難事。下面看來簡單的解釋。

 

  (1) glutCreateWindow("繪製矩形")是建立一個標題是"繪製矩形"的視窗。

  (2) glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB)函數在上面已經說過了。

  (3) glutDisplayFunc(display); 這行代碼是將前面定義的display()函數確定為顯示回呼函數。也就是說在視窗需要被繪製時,GLUT將會調用這個函數。比如說,當視窗第一次顯示或是視窗大小改變的時候,或是視窗從被覆蓋的狀態中恢複時,就會發生這個調用。這也是我們放置OpenGL渲染函數調用的地方。

  (4) glutInitWindowSize(500,500)和glutInitWindowPosition(0,0)則是分別設定視窗的大小和位置。

  (5) glutMainLoop() 這個函數很重要。這個函數啟動了GLUT架構的運行。該函數一經調用便不再返回,直到程式的結束。所以,該函數在我們的程式中只調用一次,它能處理作業系統中特定的訊息及擊鍵等事件操作,直到我們的程式結束。

 

  以上樣本的效果是在表單中繪製一個白色的矩形,如下所示:

 

  

 

  該程式示範了在OpenGL中使用GLUT建立視窗的基本原理。

  以上便是OpenGL開發中的基本原理和基礎知識。

原文出處:http://www.cnblogs.com/hanyonglu/archive/2012/05/13/2498110.html

樣本下載:/Files/hanyonglu/OpenGL/MyOpenGLDemo4.rar

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.