OpenGL入門學習(五)

2021-05-04 09:34:11 字數 3118 閱讀 8702

今天要講的是三維變換的內容,課程比較枯燥。主要是因為很多函式在單獨使用時都不好描述其效果,我只好在最後舉乙個比較綜合的例子。希望大家能一口氣看到底了。只看一次可能不夠,如果感覺到迷糊,不妨多看兩遍。有疑問可以在下面跟帖提出。

我也使用了若干圖形,希望可以幫助理解。

在前面繪製幾何圖形的時候,大家是否覺得我們繪圖的範圍太狹隘了呢?座標只能從-1到1,還只能是x軸向右,y軸向上,z軸垂直螢幕。這些限制給我們的繪圖帶來了很多不便。

我們生活在乙個三維的世界——如果要觀察乙個物體,我們可以:

1、從不同的位置去觀察它。(檢視變換)

2、移動或者旋轉它,當然了,如果它只是計算機裡面的物體,我們還可以放大或縮小它。(模型變換)

3、如果把物體畫下來,我們可以選擇:是否需要一種「近大遠小」的透視效果。另外,我們可能只希望看到物體的一部分,而不是全部(剪裁)。(投影變換)

4、我們可能希望把整個看到的圖形畫下來,但它只佔據紙張的一部分,而不是全部。(視口變換)

這些,都可以在opengl中實現。

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、操作矩陣堆疊

本文源自:http://blog.chinaunix.net/u/26313/showart_218525.html

opengl 入門學習 隨筆五

今天開始opengl的學習,下面上第乙個程式!void mydisplay int main int argc,char argv 整個程式表示顯示乙個矩形 這裡有幾個概念稍微介紹一下 1 glclear 表示清除背景,也就是說我們在黑板上清除的效果是顯示全黑,在白紙上清楚顯示的是全白 2 glut...

OpenGL入門筆記(五)

以前也聽說過紋理對映,不過一直沒明白是怎麼回事情,只是以為是在繪製好的三維圖形表面再進行更為細緻的繪製,從而繪製出物體表面的紋理,就像畫桌子把桌面的條紋也畫出來一樣。今天學習的就是如何使用2d紋理繪製圖形。紋理對映demo 總結一下,使用紋理對映分為以下幾個步驟 1 從位 件載入紋理對映所用到的點陣...

OpenGL入門學習

include 太陽 地球和月亮 假設每個月都是30天 一年12個月,共是360天 static int day 200 day的變化 從0到359 void mydisplay void void myidle void int main int argc,char argv 3 關於垂直同步co...