電腦遊戲製作開發設計論壇 首頁 電腦遊戲製作開發設計論壇
任何可以在PC上跑的遊戲都可以討論,主要以遊戲之製作開發為主軸,希望讓台灣的遊戲人有個討論、交流、教學、經驗傳承的園地
 
 常見問題常見問題   搜尋搜尋   會員列表會員列表   會員群組會員群組   會員註冊會員註冊 
 個人資料個人資料   登入檢查您的私人訊息登入檢查您的私人訊息   登入登入 

Google
GLSL&GLUT 從環境設定開始的基礎教學(02) - 關於矩陣

 
發表新主題   回覆主題    電腦遊戲製作開發設計論壇 首頁 -> 遊戲程式高級班:DirectX、OpenGL及各種圖型函式庫
上一篇主題 :: 下一篇主題  
發表人 內容
Director
偶而上來逛逛的過客


註冊時間: 2013-11-04
文章: 13

381.66 果凍幣

發表發表於: 2013-11-7, PM 8:41 星期四    文章主題: GLSL&GLUT 從環境設定開始的基礎教學(02) - 關於矩陣 引言回覆

 這章我打算跟大家稍微說明一下關於OpenGL裡面的矩陣(Model, View, Projection matrix)。

 大部分GLSL的實作都需要一點關於這三種矩陣的基本知識,相信大多數人都認得這段程式碼。
代碼:

   glMatrixMode( GL_PROJECTION );
   glLoadIdentity();
   gluPerspective( WINDOW_VISION_ANGLE, (float)w/(float)h, WINDOW_VISION_NEAR, WINDOW_VISION_FAR );

   glMatrixMode( GL_MODELVIEW );
   glLoadIdentity();
   gluLookAt( 0, 0, 1, 0, 0, 0, 0, 1, 0 );



 初學OpenGL的人一般只要記得在畫圖之前先放上這些就可以畫出東西來了。

 但是在GLSL的某些實作應用,你會只需要用到三種矩陣裡面的其中一種。

 到這邊可能有人會問,glMatrixMode不是只能夠定義兩種矩陣嗎? 要怎麼把ModelView分開成Model跟View matrix?

 那麼,他們的簡介就開始了。

 事實上我沒有要完全把他們的數學意義通通說明,這樣就會跟數學課一樣無聊了 Embarassed
 (有興趣的可以參考這篇http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/)

 我的重點在於,要如何在你的OpenGL程式內得到這三種矩陣。

 有些人會選擇自己仿作一個一模一樣的class來放置矩陣資料,這樣可能比較簡單明瞭,但我在學習的時候不知道是哪裡出了岔子,只要不用gluLookAt我的camera就會出問題 Crying or Very sad
 就結果論,取得三種矩陣的方法如下,之後我們就慢慢解釋這些程式碼的意義。
代碼:

   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   gluPerspective( angle, win_size_w/win_size_h, vNear, vFar );

   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
   gluLookAt( 0, 0, 1, 0, 0, 0, 0, 1, 0 );

   glm::mat4 ProjcetionMatrix =
      glm::perspective(
      angle,
      win_size_w/win_size_h,
      vNear,
      vFar );
   glm::mat4 ViewMatrix =
      glm::lookAt(
      glm::vec3( 0, 0, 1 ),
      glm::vec3( 0, 0, 0 ),
      glm::vec3( 0, 1, 0 ) );
   glm::mat4 ModelMatrix = glm::mat4( 1.0 );



 首先,你們看到的glm就是你會需要的一個函式庫叫做OpenGL Mathematics,他裡面包含了所有OpenGL中你會需要用到的資料型態(mat4就是4*4矩陣),還有矩陣運算(perspective, lookAt)。
 (從這裡下載安裝http://glm.g-truc.net/0.9.4/index.html)

 相信各位到這邊對照一下,應該就能很快充分理解gluPerspective還有gluLookAt做的事情了,他們就是用來設定Projecion matrix還有View matrix的函式。

 建議初學OpenGL的朋友也可以順便理解一下這些是怎麼運作的。

Projection Matrix

 首先在glMatrixMode(GL_PROJECTION)的時候,我們是在說我們接下來的程式碼都是要用來調整Projection matrix的。
引言回覆:

 所以假如你在這時候用了凡是,gluPerspective、glOrtho、glOrtho2D,甚至是glLookAt、glTranslatef、glScale、glRotate,你的設定都會拿來調整Projection matrix。

 可能有點難懂。

 我想要表達的是,在程式設計上面的意義,所有調整矩陣的函式都是拿來調整"現在設定"的那個矩陣,並不是說gluPerspective就只會作用在Projection matrix,glLookAt就只能用在modelview matrix,所以一開始設定的那些碼才會有那樣既定的順序。

 簡言之,因為你設定了glMatrixMode(GL_PROJECTION)所以gluPerspective才會調整Projection matrix。

 我想這樣應該夠簡單了 Very Happy



 接下來我們看到的是glLoadIdentity,他的意思是會把"現在設定"的那個矩陣還原成單位矩陣,有點類似歸零的動作(但是不是真的設為0)。
 ※單位矩陣在線性代數裡應該都介紹過,無論什麼矩陣乘上單位矩陣,值都不會變

 接下來的gluPerspective的意思,就是你把它要的參數代進去,然後他會算出一個矩陣,然後把那個矩陣乘上"現在設定"的那個矩陣。

 我想到這裡已經相當明白了,三個函式就代表,選擇矩陣、把矩陣設成單位矩陣、然後乘上gluPerspective算出來的矩陣。

 但是既然gluPerspective算出來的矩陣乘上單位矩陣還是原來的樣子,那我們就可以理解,gluPerspective算出來的矩陣就是投影矩陣。

 所以就像下面的。
代碼:

   glm::mat4 ProjcetionMatrix =
      glm::perspective(
      angle,
      win_size_w/win_size_h,
      vNear,
      vFar );



 我想這個是比較簡單的,那麼接下來是Model跟View matrix。


Model Matrix

 我覺得先介紹Model matrix會比較好。

 我不知道有沒有人曾經跟我一樣 Embarassed ,誤認gluLookAt會同時設定Model matrix還有View matrix,或者覺得畫圖會影響到Model matrix(他的名子看起來就讓人覺得跟物件有關係呀 Shocked )。

 假如沒有的話,其實可以跳過這段,假如有類似問題的話,那我們就接下來看下去。

 事實上,Model matrix的功能只有一個,把物件的參考座標轉換成世界座標。

 什麼是世界座標?

 一般來說,我是指一般來說,在立體空間我們會以x=0, y=0, z=0也就是(0, 0, 0)這個座標當作基準。
 也就是說,當我說一個點在(4, 0, 0),我們無形中就是在表示這個點的位置是在(0, 0, 0)的 "x軸" 正向 "4單位距離" 的地方。
 我想這個是高中數學,應該大家都沒問題的。

 而重點就在這裡,我們在OpenGL設定的glVertex3f(4, 0, 0)不是指一個坐落於座標(4, 0, 0)的點,而是我上面說的基於基準點的 "x軸" 正向 "4單位距離" 位置

 那麼,假如我把基準點改成(2, 0, 0),那glVertex3f(4, 0, 0)就會給我一個坐落於座標(6, 0, 0)的點。
 於是我們就來看看基準點和Model matrix是怎樣子的關係。
引言回覆:

 這是一個glLoadIdentity之後的Model matrix。


 所謂的基準點是在最下面三行的左邊三個。


 在glVertex設定的數字假如乘上這個Model matrix,最後得到的座標點就會像剛剛上面說的從(4, 0, 0)變成(6, 0, 0),大家可以自己拿筆算算看這個。





 那麼,簡單來說Model matrix就是一個把glVertex設定的值轉換成真正座標的矩陣。

 題外話,我上面用的圖片其實只有說到基準點也就是位移的部分,事實上我們通常會用glTranslate(位移)、glScale(縮放)、glRotate(旋轉),這三種函數去改變Model matrix。

 大多時候,我們會保持Model matrix一直是單位矩陣,因為我們想要glVertex3f(4, 0, 0),那個點就在(4, 0, 0),我們不想要去考慮基準點的問題。

引言回覆:

 Push PopMatrix原理


 這也是題外話。

 當我們在畫立體圖形的時候,要讓它整個位移,我們不想要一個點一個點分座標去算,我們就會用到glTranslate,可是假如直接用通常會出現整個世界都被位移了的問題。

 在這邊大家都會用glPushMatrix和glPopMatrix把glTranslate和glVertex包住,像這樣。
代碼:

   glPushMatrix();
   glTranslatef( 2.0, 0.0, 0.0 );

   glBegin( GL_QUADS );
      glVertex3f( 3, 0, 3 );
      glVertex3f( 3, 0, -3 );
      glVertex3f( -3, 0, -3 );
      glVertex3f( -3, 0, 3 );
   glEnd();

   glPopMatrix();



 你可以想像它是這麼做的。

 glPushMatrix複製了一個跟現在一樣的Model matrix(單位矩陣),然後把它做glTranslate(2, 0, 0),得到一個基準點(2, 0, 0)的Model matrix,然後當glVertex送上(3, 0, 3)的時候,會被Model matrix轉換過,變成(5, 0, 3)之後再送交給OpenGL畫圖。

 glPopMatrix就把你剛剛複製並且改變的那個矩陣刪除掉,然後你原來的Model matrix依舊是單位矩陣。

 glScale、glRotate會包在Push跟PopMatrix也是一樣的意思。



 最後補充一下。


 T的位置,從左至右就是使用glTranslate的(x, y, z)。
 S的位置,從左至右就是使用glScale的(x, y, z)。

 有興趣的都可以拿筆算算看。
 
 於是乎,講了好久,只要一直有在利用Push和PopMatrix來調整點,那這一行通常就等於我們的Model matrix Very Happy
代碼:

   // 這樣的宣告方式就是單位矩陣的意思
   glm::mat4 ModelMatrix = glm::mat4( 1.0 );




View Matrix

 我想這應該就不用多說了,既然我們的Model matrix一直都保持單位矩陣,那自然gluLookAt設定的就只有View matrix。

 所以View matrix就等同於。
代碼:

   glm::mat4 ViewMatrix =
      glm::lookAt(
      glm::vec3( 0, 0, 1 ),
      glm::vec3( 0, 0, 0 ),
      glm::vec3( 0, 1, 0 ) );



 利用glm提供的函數,我們可以很快速的得到它。

 那麼希望大家看完之後能夠對矩陣有更多的認識,這些對於我之後要寫的範例程式來說都相當重要,那麼就先這樣。

 Happy coding!


Director 在 2013-11-23, PM 9:46 星期六 作了第 1 次修改
回頂端
檢視會員個人資料 發送私人訊息 發送電子郵件 參觀發表人的個人網站
撲殺兔
時常出沒的會員


註冊時間: 2009-05-18
文章: 30

219.89 果凍幣

發表發表於: 2013-11-7, PM 10:31 星期四    文章主題: 引言回覆

有講到基本,推
回頂端
檢視會員個人資料 發送私人訊息
Director
偶而上來逛逛的過客


註冊時間: 2013-11-04
文章: 13

381.66 果凍幣

發表發表於: 2013-11-23, PM 9:43 星期六    文章主題: 引言回覆

撲殺兔 寫到:
有講到基本,推


 謝謝哦 Very Happy

 我只希望能拋磚引玉,希望有更多學習很久的人可以分享心得,GLSL的中文資源真的太少>_<

 也希望大家能夠用正確的概念來看待自己寫的程式,而不是模仿完就算了 Very Happy
回頂端
檢視會員個人資料 發送私人訊息 發送電子郵件 參觀發表人的個人網站
從之前的文章開始顯示:   
發表新主題   回覆主題    電腦遊戲製作開發設計論壇 首頁 -> 遊戲程式高級班:DirectX、OpenGL及各種圖型函式庫 所有的時間均為 台灣時間 (GMT + 8 小時)
1頁(共1頁)

 
前往:  
無法 在這個版面發表文章
無法 在這個版面回覆文章
無法 在這個版面編輯文章
無法 在這個版面刪除文章
無法 在這個版面進行投票
可以 在這個版面附加檔案
可以 在這個版面下載檔案


Powered by phpBB © 2001, 2005 phpBB Group
正體中文語系由 phpbb-tw 維護製作