當(dāng)前位置:首頁 > 芯聞號 > 充電吧
[導(dǎo)讀]下面這篇文章詳細講述了OpenGL里的坐標轉(zhuǎn)換,清晰,明了。但是其所謂的渲染管線只包括modelview 轉(zhuǎn)換 和 投影變換,我覺得不是這樣的。這只是從坐標角度吧。比如什么頂點著色、光柵化、送至幀緩存

下面這篇文章詳細講述了OpenGL里的坐標轉(zhuǎn)換,清晰,明了。但是其所謂的渲染管線只包括modelview 轉(zhuǎn)換 和 投影變換,我覺得不是這樣的。這只是從坐標角度吧。比如什么頂點著色、光柵化、送至幀緩存都沒有涉及到。

1.?OpenGL?渲染管線

OpenGL渲染管線分為兩大部分,模型觀測變換(ModelView Transformation)和投影變換(Projection Transformation)。做個比喻,計算機圖形開發(fā)就像我們照相一樣,目的就是把真實的場景在一張照相紙上表現(xiàn)出來。那么觀測變換的過程就像是我們擺設(shè)相機的位置,選擇好要照的物體,擺好物體的造型。而投影變換就像相機把真實的三維場景顯示在相紙上一樣。下面就分別詳細的講一下這兩個過程。

1.1模型觀測變換

讓我們先來弄清楚OpenGL中的渲染管線。管線是一個抽象的概念,之所以稱之為管線是因為顯卡在處理數(shù)據(jù)的時候是按照一個固定的順序來的,而且嚴格按照這個順序。就像水從一根管子的一端流到另一端,這個順序是不能打破的。先來看看下面的圖1:

???????????????????? 圖1 OPENGL渲染管線?????????????????????????????????

圖中顯示了OpenGL圖形管線的主要部分,也是我們在進行圖形編程的時候常常要用到的部分。一個頂點數(shù)據(jù)從圖的左上角(MC)進入管線,最后從圖的右下角(DC)輸出。MC是Model Coordinate的簡寫,表示模型坐標。DC是Device Coordinate的簡寫,表示設(shè)備坐標。當(dāng)然DC有很多了,什么顯示器,打印機等等。這里DC我們就理解成常說的屏幕坐標好了。MC當(dāng)然就是3D坐標了(注意:我說的3D坐標,而不是世界坐標),這個3D坐標就是模型坐標,也說成本地坐標(相對于世界坐標)。MC要經(jīng)過模型變換(Modeling Transformation)才變換到世界坐標,圖2:

圖2 世界坐標系和模型坐標系

變換到世界坐標WC(World Coordinate)說簡單點就是如何用世界坐標系來表示本地坐標系中的坐標。為了講得更清楚一些,這里舉個2D的例子。如圖3:

圖3 世界坐標系和模型坐標系的計算

圖中紅色坐標系是世界坐標系WC,綠色的是模型坐標系MC。現(xiàn)在有一個頂點,在模型坐標系中的坐標為(1,1),現(xiàn)在要把這個模型坐標轉(zhuǎn)換到世界坐標中來表示。從圖中可以看出,點(1,1)在世界坐標系中的坐標為(3,4),現(xiàn)在我們來通過計算得到我們希望的結(jié)果。首先我們要把模型坐標系MC在世界坐標系中表示出來,使用齊次坐標(Homogeneous Coordinate )可以表示為矩陣(注意,本教程中使用的矩陣都是以列向量組成):其中,矩陣的第一列為MC中x軸在WC中的向量表示,第二列為MC中y軸WC中的向量表示,第三列為MC中的原點在WC中的坐標。對齊次坐標系不了解的同學(xué),請先學(xué)習(xí)游戲數(shù)學(xué)方面的知識。有了這個模型變換矩陣后,用這個矩陣乘以在MC中表示的坐標就可以得到該坐標在世界坐標系中的坐標。所以該矩陣和MC中的坐標(1,1)相乘有:

這也正是我們需要的結(jié)果?,F(xiàn)在讓我們把相機坐標也加進去,相機坐標也稱為觀測坐標(View Coordinate),如圖4和圖5。

圖4 ModelView變換的三個坐標系

圖5 ModelView變換計算

來看看MC坐標中的點(1,1)如何在相機坐標中表示。從圖5中可以直接看出MC中的點(1,1)在相機坐標系VC中為(-2,-2)。和上面同樣的道理,我們可以寫出相機坐標系VC在世界標系WC中可以表示為:

那么世界坐標系中的點轉(zhuǎn)換為相機坐標系中的點我們就需求VC的逆矩陣:

那么世界坐標系WC中的點(3,4)在相機坐標系VC中坐標為:

上面的變換過程,就是可以把模型坐標變換為相機坐標。在OpenGL中,當(dāng)我們申明頂點的時候,有時候說的是世界坐標,這是因為初始化的時候世界坐標系、模型坐標系和相機坐標系是一樣的,重合在一起的。所以O(shè)penGL中提供了模型觀測變換,它是把模型坐標系直接轉(zhuǎn)換為相機坐標系,如圖4。現(xiàn)在我們已經(jīng)計算得到了VC-1和MC,如果把VC-1和MC相乘,就可以得到模型坐標在相機坐標中的表示。為了得到模型坐標系中的坐標在相機坐標系中的表示,這就是OpenGL中的ModelView變換矩陣。這也是ModelView變換的名字的由來,它是通過了上面兩個步驟得到的。那么這里,ModelView變換矩陣M為:

現(xiàn)在只要用上面的模型觀測矩陣M乘以模型坐標系MC中的坐標就可以得到相機坐標系中的坐標了。模型觀測變換的關(guān)鍵就是要得到相機坐標系中的坐標,因為光照等計算都是在這個這個坐標系中完成的。下面我們實際OpenGL程序中檢查一下。在程序中,為了計算方便,我們使用圖6中的模型。

圖6 ModelView變換計算模型

根據(jù)圖中的數(shù)據(jù),我們分別可以寫出對應(yīng)MC和VC-1,從而求得觀測變換矩陣M。

現(xiàn)在程序中用glGetFloatv()這個函數(shù)來獲得當(dāng)前矩陣數(shù)據(jù)來檢查一下。


[cpp] view plaincopyfloat?m[16]?=?{0};?//用來保存當(dāng)前矩陣數(shù)據(jù)??glMatrixMode(GL_MODELVIEW);??glLoadIdentity();??glGetFloatv(GL_MODELVIEW_MATRIX,?m);???//相機設(shè)置,View?變換??gluLookAt(0.0,?0.0,?5.0,??0.0,?0.0,?0.0,??0.0,?1.0,?0.0);??glGetFloatv(GL_MODELVIEW_MATRIX,?m);???//投影設(shè)置??glMatrixMode(GL_PROJECTION);??glLoadIdentity();??glOrtho(-10,10,-10,10,-10,10);??glMatrixMode(GL_MODELVIEW);???//Modeling變換??glTranslatef(0,?0,?-3);??glGetFloatv(GL_MODELVIEW_MATRIX,?m);??glBegin(GL_POINTS);??glVertex3f(1,1,0);??glEnd();??

如果在上面程序段中最后一個glGetFloatv(GL_MODELVIEW_MATRIX, m)處設(shè)定斷點的話,就可以看到圖7所顯示的數(shù)據(jù)。

圖7 ModelView變換矩陣數(shù)據(jù)

到這里,整個ModelView變換就完成了。通過ModelView變換后得到是相機坐標系內(nèi)的坐標。在這個坐標系內(nèi)典型的計算就是法線了?,F(xiàn)在再來看看后面一個階段。

?

//////////////////////////////////////////////////////////////

我的理解:ModelView 變換矩陣,就是完成從模型坐標到View坐標的轉(zhuǎn)換,是坐標系之間的大變換。注意,modelview 既有model,也有view。不只是一個model的矩陣。

只是對model的進行平移或旋轉(zhuǎn)的函數(shù)為 ?glTranslatef等函數(shù),稱作模型變換!它的坐標是基于模型本身的,即位于模型坐標系類,比如glTranslatef(0,?0,?-3);的3個坐標值。

只是針對view進行設(shè)置的函數(shù)為 ?gluLookAt,它的坐標系是view坐標系,比如

gluLookAt(0.0,?0.0,?5.0,?? 0.0,?0.0,?0.0,?? 0.0,?1.0,?0.0);它里面的坐標的原點位于相機坐標系的原點。參看下面的投影變換。


/////////////////////////////////////////////////////////////////


1.2投影變換

先還是復(fù)習(xí)一下OpenGL的渲染管線。圖1中可以看到,在投影變換(Projection Transformation)中也分為兩個部分,第一個部分是將上個階段得到的坐標轉(zhuǎn)換為平面坐標,第二個部分是將轉(zhuǎn)換后的平面坐標在進行歸一化并進行剪裁。一般地,將三維坐標轉(zhuǎn)換為平面坐標有兩種投影方式:正交投影(Orthogonal Projection)和透視投影(Perspective Projection)。

1.2.1?正交投影

正交投影很簡單,如圖8,對于三維空間中的坐標點和一個二維平面,要在對應(yīng)的平面上投影,只需將非該平面上的點的坐標分量改為該平面上的坐標值,其余坐標不變。

圖8 正交投影

比如將點(1,1,5)正交投影到z=0的平面上,那么投影后的坐標為(1,1,0)。在openGL中,設(shè)置正交投影可以使用函數(shù):


[cpp] view plaincopyglOrtho?(GLdouble?left,?GLdouble?right,?GLdouble?bottom,?GLdouble?top,?GLdouble?zNear,?GLdouble?zFar)??

該函數(shù)可以設(shè)置正交投影的投影空間,在該空間以外的坐標點就不會被投影到投影平面上。函數(shù)中的六個參數(shù)分是投影空間六個平面,如圖9:

圖9 OpenGL正交投影空間和投影變換

在圖9中,大的投影空間是根據(jù)這六個參數(shù)設(shè)置的投影空間,OpenGL會自動將該空間歸一化,也就是將該空間或立方體轉(zhuǎn)化為變長為1的正六面體投影空間,并且該證六面體的中心在相機坐標系的原點。一旦設(shè)置使用glortho函數(shù)設(shè)置投影空間,OpenGL會生成投影矩陣。這個矩陣的作用就是將坐標進行正交投影并且將投影后的坐標正規(guī)化(轉(zhuǎn)換到-1到1之間)。要注意的是,生成該矩陣的時候,OpenGL會把右手坐標系轉(zhuǎn)換為左手坐標系。原因很簡單,右手坐標系的Z軸向平面外的,這樣不符合我們的習(xí)慣。該矩陣的矩陣推導(dǎo)這里就不詳細說明了,不了解的同學(xué)可以參考游戲數(shù)學(xué)方面資料,這里只給出正交投影矩陣。

這個矩陣看來很復(fù)雜,其實計算很簡單。舉個例子,現(xiàn)在設(shè)置了這樣的正交投影空間glOrtho(-10,10,-10,10,-10,10),這是個正六面體空間,變長為10。把這些參數(shù)帶入上面的矩陣可以得到

現(xiàn)在還是在OpenGL程序中來檢查一下。在OpenGL程序中添加下面代碼段:


[cpp] view plaincopy//投影設(shè)置??glMatrixMode(GL_PROJECTION);??glLoadIdentity();??glOrtho(-10,10,-10,10,-10,10);??glMatrixMode(GL_MODELVIEW);??glGetFloatv(GL_PROJECTION_MATRIX,m)??

在glGetFloatv(GL_PROJECTION_MATRIX,m)處設(shè)定斷點就可以看到圖10中所顯示的信息。

圖10 正交變換矩陣數(shù)據(jù)?

1.2.2透視投影

透視投影和正交投影最大的區(qū)別就是透視投影具有遠近感。

圖11 透視投影

透視投影采用了圖11中的模型,這樣的模型就是保證遠的物體看起來小,近的物體看起來大。 在OpenGL中設(shè)置透視投影可以使用函數(shù):


[cpp] view plaincopyvoid?APIENTRY?gluPerspective?(GLdouble?fovy,?GLdouble?aspect,?GLdouble?zNear,?GLdouble?zFar);??

該函數(shù)也會根據(jù)給定的參數(shù)生成一個投影空間。如圖11中,該投影空間是一個截頭體。同樣地,OpenGL會自動生成透視投影矩陣,該矩陣也會讓3D坐標投影在投影平面上,并且將投影后的坐標也進行正規(guī)化。下面也直接給出OpenGL中使用的透視投影矩陣。

下面在OpenGL中添加下面代碼段:


[cpp] view plaincopy//投影設(shè)置??glMatrixMode(GL_PROJECTION);??glLoadIdentity();??gluPerspective(45,?1.0,?1.0,?100);??glMatrixMode(GL_MODELVIEW);??glGetFloatv(GL_PROJECTION_MATRIX,m)??

設(shè)置斷點后,我們可以看到圖12中顯示的數(shù)據(jù)。

圖12 透視變換矩陣數(shù)據(jù)

到此為止,整個投影變換就完成了。透過投影變換后得到的是正規(guī)化的投影平面坐標。這為下一個階段的視口變換(View port Transformation)做好了準備。

1.3視口變換

現(xiàn)在到了最后一個階段了。這個階段叫做視口變換,它把上個階段得到的正規(guī)化的投影坐標轉(zhuǎn)化為windows 窗口坐標。視口變換會將投影平面上的畫面映射到窗口上。在OpenGL中可以使用函數(shù)


[cpp] view plaincopyGLAPI?void?GLAPIENTRY?glViewport?(GLint?x,?GLint?y,?GLsizei?width,?GLsizei?height);??

來進行對窗口的映射,如圖13。


圖13 視口變換glViewport(width/2, 0, width/2, height/2)

舉個例子說明,比如上個階段中得到了一個頂點的坐標為(0,0,0.5,1),根據(jù)這個坐標,該頂點位于投影平面的正中間。如果將該點映射到大小為50*50的窗口上時,那么它應(yīng)該位于屏幕的中間,坐標為(25,25, 0.5,1)。當(dāng)然這里深度值0.5是不會改變的。有的同學(xué)肯定有疑問了,既然投影到了窗口上,那么還要深度值0.5干什么?這里要注意的是,雖然在窗口上顯示時只需要x,y坐標就夠了,但是要在2D窗口上顯示3D圖形時深度值是不可少的。這里的深度值不是用于顯示,而是用于在光柵化的時候進行深度測試。

OpenGL也會根據(jù)glViewport函數(shù)提供的參數(shù)值生成一個視口變換矩陣

該矩陣把上個階段得到的正規(guī)化坐標映射到窗口上,并且將正規(guī)化坐標中的深度值在轉(zhuǎn)換到0到1之間。所以在深度緩沖中最大值為1,最小值為0。視口變換結(jié)束后,OpenGL中主要的圖形管線階段就算完成了,后面就是光柵化等等操作。再來回顧一下圖1,現(xiàn)在相信大家對這個渲染管線有了一定的認識了,也明白了每一個階段對應(yīng)的變換矩陣以及如何進行坐標之間的轉(zhuǎn)換的。

2.?屏幕坐標轉(zhuǎn)換為世界坐標

通過前面的教程,以及現(xiàn)在大家對OpenGL整個渲染管線理解后,現(xiàn)在要將屏幕上一點坐標轉(zhuǎn)換為世界坐標就比較容易了。從圖形管線的開始到結(jié)束,一個模型坐標系中的坐標被轉(zhuǎn)化為了屏幕坐標,那么現(xiàn)在把整個過程倒過來的話,屏幕上一點坐標也可以轉(zhuǎn)為為世界坐標。只要在對應(yīng)的階段求得對應(yīng)變換矩陣的逆矩陣,就可以得到前一個階段的坐標。這整個過程可以用圖14表示。

圖14屏幕坐標轉(zhuǎn)換為世界坐標

圖中顯示的過程完全就是OpenGL渲染管線的逆過程,通過這個過程,屏幕上的點就可以轉(zhuǎn)化為世界坐標系中的點了。可能又有的同學(xué)要問,當(dāng)鼠標點擊屏幕上一點的時候并沒有深度信息,轉(zhuǎn)換的時候要怎么辦呢?這個時候可以使用OpenGL函數(shù)


[cpp] view plaincopyvoid?glReadPixels?(GLint?x,?GLint?y,?GLsizei?width,?GLsizei?height,?GLenum?format,?GLenum?type,?GLvoid?*pixels);??

該函數(shù)能夠獲得屏幕上一點對應(yīng)像素的深度信息。有了這個深度信息,就可以利用上面過程把屏幕上一點轉(zhuǎn)換為世界坐標了。在OpenGL中,上面的過程其實已經(jīng)有現(xiàn)成的函數(shù)可以使用,那就是


[cpp] view plaincopyint?APIENTRY?gluUnProject?(??????GLdouble??winx,?GLdouble??winy,??????GLdouble??winz,??????const?GLdouble?modelMatrix[16],??????const?GLdouble?projMatrix[16],??????const?GLint????viewport[4],??????GLdouble??*objx,??GLdouble??*objy,??????GLdouble???????*objz);??

該函數(shù)直接將屏幕上一點轉(zhuǎn)換對應(yīng)的世界坐標,該函數(shù)的內(nèi)部實現(xiàn)其實還是上面的那么逆過程。下面給出利用該函數(shù)獲取世界坐標的代碼段。


[cpp] view plaincopyGVector?screen2world(int?x,?int?y)??{?????????GLint?viewport[4];?????????GLdouble?modelview[16];?????????GLdouble?projection[16];?????????GLfloat?winX,?winY,?winZ;?????????GLdouble?posX,?posY,?posZ;?????????glGetDoublev(GL_MODELVIEW_MATRIX,?modelview);?????????glGetDoublev(GL_PROJECTION_MATRIX,?projection);?????????glGetIntegerv(GL_VIEWPORT,?viewport);?????????winX?=?(float)x;?????????winY?=?(float)viewport[3]?-?(float)y;?????????glReadPixels(x,?int(winY),?1,?1,?GL_DEPTH_COMPONENT,?GL_FLOAT,?&winZ);?????????gluUnProject(winX,?winY,?winZ,?modelview,?projection,?viewport,?&posX,?&posY,?&posZ);?????????GVector?v(4,?posX,?posY,?posZ,?1.0);?????????return?v;??}??

代碼中函數(shù)返回類型GVector是用戶定義的向量類,返回的是齊次坐標。
本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險,如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學(xué)會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉