OpenGL编程指南7:视图-
生活随笔
收集整理的這篇文章主要介紹了
OpenGL编程指南7:视图-
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
1.前言
計算機圖形學的要點就是創(chuàng)建三維物體的二維圖像(圖像必須是二維的,因為他是在平面的屏幕上顯示的)。但是,當我們決定怎樣在屏幕上繪圖時,必須使用三維坐標的方式考慮。 為了把一個物體的三維坐標變成屏幕上的像素坐標,需要完成以下三個步驟:- 變換包括模型、視圖和投影操作,這是通過矩陣乘法表示的。這些操作包括:旋轉(zhuǎn)、移動、縮放、反射、正投影和透視投影等。一般情況下,在繪制場景時,需要組合幾種變換。
- 由于場景是在一個矩形窗中渲染的,因此位于窗口之外的物體(或物體的一部分)必須裁減掉。在三維計算機圖形學中,剪裁就是丟棄位于裁剪平面之外的物體。
- 經(jīng)過了變換之后的坐標與屏幕像素之間必須建立對應關(guān)系,這個過程就是視口變換。
OpenGL采用投影矩陣來完成剪裁坐標,這個變換定義了一個視景體,位于這個空間之外的物體將裁剪掉,不會在最終的場景中出現(xiàn)。 隨后發(fā)生的是透視除法,他把坐標除以w,產(chǎn)生規(guī)范化的設備坐標。 最后,變換后的坐標通過視口變換成窗口坐標,可以通過控制視口的大小對最終的圖像進行放大、縮小或拉伸。
2.詳細理解各個變換
1. 一個例子
#include <vgl.h>void init(void) {glClearColor(0.0,0.0,0.0,0.0);glShadeModel(GL_FLAT); } void display(void) {glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0,1.0,1.0);glLoadIdentity();gluLookAt(0.0,0.0,5.0,0.0,0.0,0.0, 0.0,1.0,0.0);glScalef(1.0,2.0,1.0);glutWireCube(1.0);glFlush(); } void reshape(int w, int h) {glViewport(0,0,(GLsizei)w,(GLsizei)h);glMatrixMode(GL_PROJECTION);glLoadIdentity();glFrustum(-1.0,1.0,-1.0,1.0,1.5,20.0);glMatrixMode(GL_MODELVIEW); } int main(int argc, char** argv) {glutInit(&argc,argv);glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);glutInitWindowSize(500,500);glutInitWindowPosition(100,100);glutCreateWindow(argv[0]);init();glutDisplayFunc(display);glutReshapeFunc(reshape);glutMainLoop();return 0; }輸出結(jié)果:2.2 視圖變換
視圖變換相當于把照相機固定在三腳架上并使它對準場景。上面例子中,在指定視圖變換之前,需要使用glLoadIndentity()函數(shù)將當前矩陣設置為單位矩陣,這一步是非常必要的!!!因為絕大多數(shù)的變換是將當前矩陣與指定的矩陣相乘,然后把結(jié)果指定為當前矩陣。如果沒有通過加載單位矩陣來清除當前矩陣,它所進行的變換實際上是把當前的變換與上一次變換進行組合。當然啦,在某些情況確實需要這種組合變換,但是大多數(shù)情況下,還是要清除當前矩陣的。 上例中,先進行矩陣初始化,然后使用glLookAt()函數(shù)指定了視圖變換。這個函數(shù)實際上就是眼睛/照相機的位置、瞄向以及朝上方向。void gluLookAt(GLdouble eyeX , GLdouble eyeY , GLdouble eyeZ , //相機位置GLdouble centerX , GLdouble centerY , GLdouble centerZ , //相機焦點GLdouble upX , GLdouble upY , GLdouble upZ ); //相機向上方向gluLookAt(0.0,0.0,5.0,0.0,0.0,0.0,0.0,1.0,0.0);這里設定的參數(shù)是把攝像機放在了(0,0,5)的位置;鏡頭瞄準(0,0,0);朝向為(0,1,0);需要注意的是朝上向量為攝像機指定了唯一的方向。 Attention!!! 如果沒有調(diào)用gluLookAt()函數(shù),那么攝像機就會采用默認的位置和方向。默認情況下,照相機位于原點,指向z軸的負方向,朝上向量為(0,1,0);
2.3 模型變換
模型變換的目的是設置模型的位置和方向。可以對模型進行旋轉(zhuǎn)、移動和縮放等操作。上例僅采用了縮放這個參數(shù)。 void glScalef(GLfloat x, GLfloat y, GLfloat z); //縮放。參數(shù)指定在那個方向上縮放 void glTranslatef(GLfloat x, GLfloat y, GLfloat z); //移動。 void glRotatef(GLfloat angle, GLfloat x,GLfloat y,GLfloat z); //從原點到點(x,y,z)的直線進行旋轉(zhuǎn)的角度。2.3 投影變換
投影變換的目的在于確定視野,并因此確定那些物體位于視野之內(nèi)以及他們能夠被看到的程度。和攝像機非常類似,好比選擇廣角鏡頭、標準鏡頭還是長焦鏡頭。使用廣角鏡頭的場景范圍要遠大于長焦鏡頭。但是長焦鏡頭可以使遠處的物體看上去比實際更靠近相機。 除了視野,投影變換還決定物體是如何投影到屏幕上的。OpenGL提供了兩種基本類型的投影。其一是透射投影,另一種是正投影。- 透射投影
glFrustrum定義了一個平截頭體,它計算一個用于實現(xiàn)透視投影的矩陣,并把它與當前的投影矩陣(一般為單位矩陣)相乘。
Attention!!! 平截頭體并不要求一定是對稱的,它的軸也不需要與Z軸對齊。
glFrustrum使用起來不是很直觀,我們可以用OpenGL工具函數(shù)庫的gluPerspective函數(shù)。 void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);參數(shù)fovy表示眼睛張開的角度。 aspect表示縱橫比x/y。 zNear和zFar分別表示觀察者離近遠裁剪平面的距離。
注意:gluPerspective僅限于創(chuàng)建沿視線方向同時對稱與x軸和y軸的平截頭體。 但是我們通常所需要的也就是這種平截頭體。
- 正投影
如果是把二維圖像投影到二維屏幕這種情況,可以使用OpenGL工具函數(shù)庫中的gluOrtho2D函數(shù)。它與它的三維版本glOrtho基本相同。
Attention!!! 在調(diào)用glFrustum()或glOrtho()設置透視投影或者正投影之前,需要做一些準備工作。 首先,需要以GL_PROJECTION為參數(shù)調(diào)用glMatrixMode()函數(shù),表示把當前矩陣指定為用于偷用變換。 然后,設置投影矩陣初始化為單位陣。 接著,設定采用透射投影還是正投影。 最后,以GL_MODELVIEW為參數(shù)再次調(diào)用glMatrixMode()函數(shù),表示以后的變換所影響的是模型視圖矩陣而不再是投影矩陣。
glMatrixMode(GL_PROJECTION); //開始投影變換glLoadIdentity();//glFrustum(-1,1.0,-1,1,1.5,5.5); //透視變換glOrtho(-1,1.0,-5,5,0.5,20); //正投影glMatrixMode(GL_MODELVIEW); //結(jié)束投影變換轉(zhuǎn)到視圖變換Attention!!! 上例中,reshape()函數(shù)同時包括投影變換和視口變換。
當窗口初次創(chuàng)建時,或者當窗口移動或改變形狀時,reshape()函數(shù)都會被調(diào)用。這是很合理的,因為投影(投影視景體的寬度-高度縱橫比)和視口都是與屏幕直接相關(guān)的,特別是與屏幕窗口的大小或縱橫比直接相關(guān)。
2.4 視口變換
投影變換和視口變換共同決定了場景是如何映射到計算機屏幕的。投影變換指定了投影的發(fā)生機制,而視口變換則決定了場景所映射的有效屏幕區(qū)域的形狀。由于視口指定了場景在屏幕上所占據(jù)的區(qū)域,因此,可以吧視口變換看成是定義了最終經(jīng)過處理的照片的大小和位置。例如,照片是否應該放大或者縮小。void glViewport(GLint x, GLint y, GLsizei width, GLsizei height); //設置視口及像素將要顯示的區(qū)域。(注意(0,0)表示窗口的左下角) glViewport()參數(shù)描述了窗口內(nèi)部有效屏幕空間的遠點。上例中為(0,0)。另外,該函數(shù)也描述了有效屏幕區(qū)域的寬度與高度。該函數(shù)需要在reshape()函數(shù)內(nèi)部調(diào)用,用于響應窗口的變化。2.5 繪制場景
指定了視圖-模型變換、投影-窗口變換后就可以繪制場景了。在繪制場景時,OpenGL通過模型和視圖變換對場景中每個物體的每個頂點進行變換。然后,根據(jù)指定的投影變換對每個定點進行變換。如果頂點位于視景體之外,就會被裁剪掉。最后剩余的頂點除以W,然后映射到視口中。3.參考資料
[1] 施萊爾, GrahamSellers, JohnKessenich,等. OpenGL編程指南[M]. 機械工業(yè)出版社, 2014.總結(jié)
以上是生活随笔為你收集整理的OpenGL编程指南7:视图-的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 不朽著作《飞鸽》
- 下一篇: OpenGL编程指南8:模型组合变换