title: OpenGL坐標(biāo)系
date: 2015-3-14
tags: OpenGL
坐標(biāo)系統(tǒng)
想要弄懂幾何變換碍现,一定要搞清楚OpenGL中的坐標(biāo)系統(tǒng)。
從我們構(gòu)造模型的局部坐標(biāo)系(Local/Object Space)經(jīng)過(guò)一系列處理最終渲染到屏幕坐標(biāo)(Screen Space)下晓勇,這過(guò)程中有6種坐標(biāo)系畜伐。
- World Coordinates(世界坐標(biāo)系)
- Object Coordinates(對(duì)象坐標(biāo)系、模型坐標(biāo)系想际、局部坐標(biāo)系或當(dāng)前繪圖坐標(biāo)系)
- Eye Coordinates(眼坐標(biāo)系或照相機(jī)坐標(biāo)系)
- Clip Coordinates(裁剪坐標(biāo)系)
- Normalized Device Coordinates (NDC) (歸一化設(shè)備坐標(biāo)系)
- Window Coordinates (Screen Coordinates)(屏幕坐標(biāo))
繪制管線如圖所示:
實(shí)際上棉饶,并不存在單獨(dú)的模型變換(Model)和視點(diǎn)變換(View),通常將這兩種變換合稱為ModelView變換涂籽。則OpenGL的頂點(diǎn)變換過(guò)程如圖所示:
世界坐標(biāo)系
世界坐標(biāo)系始終是固定不變的。OpenGL使用右手坐標(biāo),這里有一個(gè)形象的方法:使用右手定則
X 是你的拇指
Y 是你的食指
Z 是你的中指
如果你把你的拇指指向右邊衡蚂,食指指向天空,那么中指將指向你的背后薄榛。我們的觀察方向是Z軸負(fù)半軸的方向讳窟。
進(jìn)行旋轉(zhuǎn)操作時(shí)需要指定的角度θ的方向則由右手法則來(lái)決定,即右手握拳敞恋,大拇指直向某個(gè)坐標(biāo)軸的正方向丽啡,那么其余四指指向的方向即為該坐標(biāo)軸上的θ角的正方向(即θ角增加的方向),圖中用圓弧形箭頭標(biāo)出:
![](http://image-for-blog.qiniudn.com/屏幕快照 2015-03-14 下午4.46.40.png?imageView2/2/w/300)
對(duì)象坐標(biāo)系
這是對(duì)象在被應(yīng)用任何變換之前的初始位置和方向所在的坐標(biāo)系硬猫,也就是當(dāng)前繪圖坐標(biāo)系补箍。該坐標(biāo)系不是固定的,且僅對(duì)該對(duì)象適用啸蜜。在默認(rèn)情況下坑雅,該坐標(biāo)系與世界坐標(biāo)系重合。這里能用到的函數(shù)有g(shù)lTranslatef()衬横,glScalef(), glRotatef()裹粤,當(dāng)用這些函數(shù)對(duì)當(dāng)前繪圖坐標(biāo)系進(jìn)行平移、伸縮蜂林、旋轉(zhuǎn)變換之后遥诉, 世界坐標(biāo)系和當(dāng)前繪圖坐標(biāo)系不再重合。改變以后噪叙,再用glVertex3f()等繪圖函數(shù)繪圖時(shí)矮锈,都是在當(dāng)前繪圖坐標(biāo)系進(jìn)行繪圖,所有的函數(shù)參數(shù)也都是相對(duì)當(dāng)前繪圖坐標(biāo)系來(lái)講的睁蕾。如圖則是對(duì)物體進(jìn)行變換后苞笨,對(duì)象坐標(biāo)系與世界坐標(biāo)系的相對(duì)位置。
![](http://image-for-blog.qiniudn.com/0_132532050582La.gif)
眼坐標(biāo)系
模型變換:對(duì)象坐標(biāo)系->世界坐標(biāo)系
視變換:世界坐標(biāo)系->眼坐標(biāo)系
為啥要轉(zhuǎn)換到眼坐標(biāo)系呢猜丹?
可以這樣理解,通過(guò)前面的MODEVIEW變換硅卢,這個(gè)世界坐標(biāo)系中的場(chǎng)景已經(jīng)繪制好了射窒。這時(shí)候我們還不能看到場(chǎng)景哦藏杖,因?yàn)槲覀兊挠^察位置還沒(méi)定呢,而且如果我們眼睛(照相機(jī))的位置不同脉顿,那么觀察物體的角度則不同蝌麸,那看到的場(chǎng)景的樣子肯定也不同,所以要有這一步艾疟,把場(chǎng)景與我們的觀察位置對(duì)應(yīng)起來(lái)来吩。
默認(rèn)情況下,眼坐標(biāo)系與世界坐標(biāo)系也是重合的蔽莱。使用函數(shù) gluLookAt()則可以指定眼睛(相機(jī))的位置和眼睛看向的方向弟疆。該函數(shù)的原型如下:
void gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez,
GLdouble centerx, GLdouble centery, GLdouble centerz,
GLdouble upx, GLdouble upy, GLdouble upz);
函數(shù)參數(shù)中,點(diǎn)(eyex, eyey, eyez)代表眼睛所在位置;
點(diǎn)(centerx, centery,centerz)代表眼睛看向的位置盗冷;
向量(upx, upy, upz)代表視線向上方向,其中視點(diǎn)和參考點(diǎn)的連線與視線向上方向要保持垂直關(guān)系怠苔。
只需控制這三個(gè)量,便可定義新的視點(diǎn)。
tips
使用glTranslatef()仪糖,glScalef(), glRotatef()這些函數(shù)是對(duì)對(duì)象坐標(biāo)系進(jìn)行變動(dòng)柑司;使用void gluLookAt()是對(duì)眼坐標(biāo)系進(jìn)行變動(dòng),兩者可以達(dá)到相同的變換效果锅劝。相當(dāng)于對(duì)象不動(dòng)移動(dòng)相機(jī)攒驰,和相機(jī)不動(dòng)移動(dòng)對(duì)象。比如場(chǎng)景向x軸正方向移動(dòng)1個(gè)單位(相機(jī)不動(dòng))故爵,相當(dāng)于相機(jī)向x軸負(fù)方向移動(dòng)一個(gè)單位(對(duì)象不動(dòng))玻粪,glTranslatef(1.0, 0.0, 0.0) <=> gluLookAt(-1.0, 0.0, 0.0, ..., ... )。
裁剪坐標(biāo)系
眼坐標(biāo)到裁剪坐標(biāo)是通過(guò)投影完成的诬垂。眼坐標(biāo)通過(guò)乘以GL_PROJECTION矩陣變成了裁剪坐標(biāo)劲室。
透視投影
類似于日常生活看到的場(chǎng)景棺克,遠(yuǎn)處物體看起來(lái)小悠垛,近處看起來(lái)大。使用透視投影函數(shù)glFrustum()和gluPerspective().
void glFrustum(GLdouble left, GLdouble right,
GLdouble bottom, GLdouble top,
GLdouble near, GLdouble far)
far, near是指近裁剪面娜谊,遠(yuǎn)剪裁面離視點(diǎn)的距離(>0),
對(duì)角坐標(biāo), (left, bottom, -near)和(right, top, -near)定義了近裁剪面的左下角和右上角的(x, y, z)坐標(biāo)确买。
void gluPerspective(GLdouble fovy, GLdouble aspect,
GLdouble near, GLdouble far)
fovy視角,aspect = w/h
![](http://image-for-blog.qiniudn.com/屏幕快照 2015-03-14 下午7.44.25.png?imageView2/2/w/320)
正投影
把物體直接映射到屏幕上纱皆,不影響它們的相對(duì)大小湾趾。也就是圖像反映物體的實(shí)際大小芭商。函數(shù)glOrtho()創(chuàng)建一個(gè)用于正交投影的平行視景體, 將其與當(dāng)前矩陣相乘。
void glOrtho(GLdouble left, GLdouble right,
GLdouble bottom, GLdouble top,
GLdouble near, GLdouble far);
![](http://image-for-blog.qiniudn.com/屏幕快照 2015-03-14 下午7.44.35.png?imageView2/2/w/320)
歸一化設(shè)備坐標(biāo)系
由裁剪坐標(biāo)系下通過(guò)除以W分量得到搀缠。這個(gè)操作稱為透視除法铛楣。NDC坐標(biāo)很像屏幕坐標(biāo),但是還沒(méi)有經(jīng)過(guò)平移和縮放到屏幕像素∫掌眨現(xiàn)在3個(gè)軸上的值范圍均為[-1,1]簸州。屏幕坐標(biāo)系
通常將屏幕上的設(shè)備坐標(biāo)稱為屏幕坐標(biāo)。設(shè)備坐標(biāo)又稱為物理坐標(biāo),是指輸出設(shè)備上的坐標(biāo)歧譬。設(shè)備坐標(biāo)用對(duì)象距離窗口左上角的水平距離和垂直距離來(lái)指定對(duì)象的位置,是以像素為單位來(lái)表示的,設(shè)備坐標(biāo)的 X 軸向右為正,Y 軸向下為正,坐標(biāo)原點(diǎn)位于窗口的左上角岸浑。
從NDC坐標(biāo)到屏幕坐標(biāo)基本上是一個(gè)線性映射關(guān)系。通過(guò)對(duì)NDC坐標(biāo)進(jìn)行視口變換得到瑰步。這時(shí)候就要用到函數(shù)glViewport()矢洲,該函數(shù)用來(lái)定義渲染區(qū)域的矩形,也就是最終圖像映射到的區(qū)域面氓。
小結(jié)
以上是我對(duì)OpenGL坐標(biāo)系統(tǒng)的學(xué)習(xí)筆記兵钮,主要參考了這篇很詳細(xì)的博文以及其中的鏈接博文。