opengl變換實際上是通過矩陣乘法來實現。無論是移動、旋轉還是縮放大小,都是通過在當前矩陣的基礎上乘以乙個新的矩陣來達到目的。關於矩陣的知識,這裡不詳細介紹,有興趣的朋友可以看看線性代數(大學生的話多半應該學過的)。
opengl可以在最底層直接操作矩陣,不過作為初學,這樣做的意義並不大。這裡就不做介紹了。
1、模型變換和檢視變換
從「相對移動」的觀點來看,改變觀察點的位置與方向和改變物體本身的位置與方向具有等效性。在opengl中,實現這兩種功能甚至使用的是同樣的函式。
由於模型和檢視的變換都通過矩陣運算來實現,在進行變換前,應先設定當前操作的矩陣為「模型檢視矩陣」。設定的方法是以gl_modelview為引數呼叫glmatrixmode函式,像這樣:
glmatrixmode(gl_modelview);
通常,我們需要在進行變換前把當前矩陣設定為單位矩陣。這也只需要一行**:
glloadidentity();
然後,就可以進行模型變換和檢視變換了。進行模型和檢視變換,主要涉及到三個函式:
gltranslate*
,把當前矩陣和乙個表示移動物體的矩陣相乘。三個引數分別表示了在三個座標上的位移值。
glrotate*
,把當前矩陣和乙個表示旋轉物體的矩陣相乘。物體將繞著(0,0,0)到(x,y,z)的直線以逆時針旋轉,引數angle表示旋轉的角度。
glscale*
,把當前矩陣和乙個表示縮放物體的矩陣相乘。x,y,z分別表示在該方向上的縮放比例。
注意我都是說「與xx相乘」,而不是直接說「這個函式就是旋轉」或者「這個函式就是移動」,這是有原因的,馬上就會講到。
假設當前矩陣為單位矩陣,然後先乘以乙個表示旋轉的矩陣r,再乘以乙個表示移動的矩陣t,最後得到的矩陣再乘上每乙個頂點的座標矩陣v。所以,經過變換得到的頂點座標就是((rt)v)。由於矩陣乘法的結合率,((rt)v) = (r(tv)),換句話說,實際上是先進行移動,然後進行旋轉。即:
實際變換的順序與**中寫的順序是相反的。
由於「先移動後旋轉」和「先旋轉後移動」得到的結果很可能不同,初學的時候需要特別注意這一點。
opengl之所以這樣設計,是為了得到更高的效率。但在繪製複雜的三維圖形時,如果每次都去考慮如何把變換倒過來,也是很痛苦的事情。這裡介紹另一種思路,可以讓**看起來更自然(寫出的**其實完全一樣,只是考慮問題時用的方法不同了)。
讓我們想象,座標並不是固定不變的。
旋轉的時候,座標系統隨著物體旋轉。移動的時候,座標系統隨著物體移動。如此一來,就不需要考慮**的順序反轉的問題了。
以上都是針對改變物體的位置和方向來介紹的。如果要改變觀察點的位置,除了配合使用glrotate*和gltranslate*函式以外,還可以使用這個函式:glulookat。它的引數比較多,前三個引數表示了觀察點的位置,中間三個引數表示了觀察目標的位置,最後三個引數代表從(0,0,0)到 (x,y,z)的直線,它表示了觀察者認為的「上」方向。
2、投影變換
投影變換就是定義乙個可視空間,可視空間以外的物體不會被繪製到螢幕上。(注意,從現在起,座標可以不再是-1.0到1.0了!)
opengl支援兩種型別的投影變換,即透視投影和正投影。投影也是使用矩陣來實現的。如果需要操作投影矩陣,需要以gl_projection為引數呼叫glmatrixmode函式。
glmatrixmode(gl_projection);
通常,我們需要在進行變換前把當前矩陣設定為單位矩陣。
glloadidentity();
透視投影所產生的結果類似於**,有近大遠小的效果,比如在火車頭內向前照乙個鐵軌的**,兩條鐵軌似乎在遠處相交了。
使用glfrustum函式可以將當前的可視空間設定為透視投影空間。其引數的意義如下圖:
宣告:該來自www.opengl.org,該是《opengl程式設計指南》一書的附圖,由於該書的舊版(第一版,2023年)已經流傳於網路,我希望沒有觸及到版權問題。
也可以使用更常用的gluperspective函式。其引數的意義如下圖:
宣告:該來自www.opengl.org,該是《opengl程式設計指南》一書的附圖,由於該書的舊版(第一版,2023年)已經流傳於網路,我希望沒有觸及到版權問題。
正投影相當於在無限遠處觀察得到的結果,它只是一種理想狀態。但對於計算機來說,使用正投影有可能獲得更好的執行速度。
使用glortho函式可以將當前的可視空間設定為正投影空間。其引數的意義如下圖:
宣告:該來自www.opengl.org,該是《opengl程式設計指南》一書的附圖,由於該書的舊版(第一版,2023年)已經流傳於網路,我希望沒有觸及到版權問題。
如果繪製的圖形空間本身就是二維的,可以使用gluortho2d。他的使用類似於glorgho。
3、視口變換
當一切工作已經就緒,只需要把畫素繪製到螢幕上了。這時候還剩最後乙個問題:應該把畫素繪製到視窗的哪個區域呢?通常情況下,預設是完整的填充整個視窗,但我們完全可以只填充一半。(即:把整個圖象填充到一半的視窗內)
宣告:該來自www.opengl.org,該是《opengl程式設計指南》一書的附圖,由於該書的舊版(第一版,2023年)已經流傳於網路,我希望沒有觸及到版權問題。
使用glviewport來定義視口。其中前兩個引數定義了視口的左下腳(0,0表示最左下方),後兩個引數分別是寬度和高度。
4、操作矩陣堆疊
介於是入門教程,先簡單介紹一下堆疊。你可以把堆疊想象成一疊盤子。開始的時候乙個盤子也沒有,你可以乙個乙個往上放,也可以乙個乙個取下來。每次取下的,都是最後一次被放上去的盤子。通常,在計算機實現堆疊時,堆疊的容量是有限的,如果盤子過多,就會出錯。當然,如果沒有盤子了,再要求取乙個盤子,也會出錯。
我們在進行矩陣操作時,有可能需要先儲存某個矩陣,過一段時間再恢復它。當我們需要儲存時,呼叫glpushmatrix函式,它相當於把矩陣(相當於盤子)放到堆疊上。當需要恢復最近一次的儲存時,呼叫glpopmatrix函式,它相當於把矩陣從堆疊上取下。opengl規定堆疊的容量至少可以容納32個矩陣,某些opengl實現中,堆疊的容量實際上超過了32個。因此不必過於擔心矩陣的容量問題。
通常,用這種先儲存後恢復的措施,比先變換再逆變換要更方便,更快速。
注意:模型檢視矩陣和投影矩陣都有相應的堆疊。使用glmatrixmode來指定當前操作的究竟是模型檢視矩陣還是投影矩陣。
OpenGL(3) OpenGL視角的計算
oepngl繪圖的過程中,讓camera指向正確的方向比較容易,然而,在使用投影函式的過程中,一定要把物體放在裁剪範圍之內,當繪製出來的物體大小不合適的時候,可能是由於使用了glperspective 函式導致的,可以通過修改函式第乙個引數的值來調整大小。那麼第乙個引數的角度 視角 是如何確定的呢?...
OpenGL滑鼠滑動實現視角旋轉
思路 攝像機圍繞著中心點,以固定的半徑做圓周運動。記錄滑鼠在螢幕上滑動的距離,縮小到適合的比例,然後計算出移動後的攝像機的x和z座標。從而達到攝像機旋轉,即視角旋轉的目的。這裡最關鍵的地方在於lookat矩陣,lookat矩陣是一種特殊型別的view矩陣,通過直接賦值給view矩陣,然後把view傳...
今天OpenGL問題
今天準備回到windows上繼續學習opengl,結果不知道是因為在虛擬機器的原因還是因為其他的,乙個基本的opengl框架竟然卡,而且關閉按鈕不接收訊息,先把 貼上來,回去在windows上實驗一下 include include include pragma comment lib,opengl...