全景视频播放器中OpenGL的相关记录
全景視頻播放器中OpenGL的相關(guān)記錄
- 一、OpenGL頂點數(shù)組
- 二、坐標系與投影
- 三、坐標系相關(guān)函數(shù)
- 四、紋理坐標
- 五、紋理過濾
- 六、深度緩沖區(qū)
- 七、OpenGL的glut庫
- OpenGL函數(shù)功能glutTimerFunc()
- glutMainLoop()循環(huán)什么?
一、OpenGL頂點數(shù)組
OpenGL頂點數(shù)組詳細介紹.(可不看)
**OpenGL頂點數(shù)組的理解.
glVertex函數(shù)調(diào)用的開銷會過大,而頂點數(shù)組就是將原來由一系列的glVertex*指定的頂點放在一個數(shù)組中(其意思就是頂點數(shù)據(jù)組成的數(shù)組)由頂點數(shù)組處理函數(shù)一次性指定。事實上,不僅如此,其一次性指定的不僅僅是數(shù)組,還可以是其他系列的東西,比如表面發(fā)現(xiàn),RGBA 顏色,輔助顏色等。
頂點數(shù)組實際上是多個數(shù)組,頂點坐標、紋理坐標、法線向量、頂點顏色等等,頂點的每一個屬性都可以指定一個數(shù)組,然后用統(tǒng)一的序號來進行訪問。比如序號3,就表示取得顏色數(shù)組的第3個元素作為顏色、取得紋理坐標數(shù)組的第3個元素作為紋理坐標、取得法線向量數(shù)組的第3個元素作為法線向量、取得頂點坐標數(shù)組的第3個元素作為頂點坐標。把所有的數(shù)據(jù)綜合起來,最終得到一個頂點。
一般代碼:
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertex_list);
glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, index_list);
二、坐標系與投影
代碼參考:glutReshapeFunc 改變窗口大小時保持圖形比例.
OpenGl的glMatrixMode()函數(shù)理解.
參考:再議gluPerspective和gluLookAt的關(guān)系.注重原理講解,講的很不錯。
首先:我們需要把顯示的物體轉(zhuǎn)換到觀察坐標系
如果物體有自己的建模坐標系,則需要把這個轉(zhuǎn)換到世界坐標系,然后再轉(zhuǎn)換到觀察坐標系.接下來進行投影
gluLookAt函數(shù)的作用,即封裝了世界坐標系到觀察坐標系的轉(zhuǎn)換
正交投影和透視投影是兩種不同的投影.類比光源
正交投影,就是有一排平行于觀察平面的法線的方向的光源,它發(fā)出一組平行線,從而不管物體離觀察平面的遠近,大小都是一樣的.
透視投影,類似于有個點光源,它會發(fā)出一組相交于一點的光線,從而相同的大小,近的物體投影的大小大,而遠一些的就小一點.
投影之后,就在觀察界面有了顯示,這就是我們最終的成像了.觀察平面從數(shù)學來說是無限大的,從我們實際使用角度,我們需要限制一個大小,這個大小也就決定了,我們哪些區(qū)域可以顯示,其他投影在別的區(qū)域就忽略.
這就是很多書上說的裁剪窗口.
這就引入以下函數(shù):
gluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar)
zNear,zFar是到觀察原點的距離(沿著z的負軸方向),因此這兩個數(shù)應(yīng)該總數(shù)設(shè)定成正數(shù).
從網(wǎng)上很多資料都在說,zNear和zFar做為一個深度的裁剪范圍,在這個范圍內(nèi)的物體才能進行投影,否則就直接忽略.初學者到這個地方,也能夠理解,但從我們上面的問題來看,我們不知道觀察平面在哪呢? 其實opengl已經(jīng)規(guī)定了,觀察平面就在近平面這里,也就是zNear指定的地方, 觀察平面是平行于觀察坐標系的(X,Y),因此我們指定z軸,也就指定它的位置.
OK,我們的觀察平面已經(jīng)確定了,那觀察平面的裁剪區(qū)域呢?
前面我們說過,觀察平面的裁剪窗口的橫縱比(w/h)最好和屏幕的一致(估計說的不準確,也就是視口的橫縱比,從而只是等比例縮放而已). 因此,gluPerspective的第二個參數(shù)就是 aspect了,這樣就把裁剪區(qū)域的寬度和高度的比例確定了.那剩下的是,我們目前還需要設(shè)定高度或者寬度.
gluPerspective的第一個參數(shù)是fovy,它是一個角度.其實通過fovy和zNear能夠計算出裁剪窗口的高度.從而我們也就決定了裁剪窗口的大小了. fovy就是視錐體的上下平面的角度.裁剪窗口的高度 h = 2 * tan(fovy/2) * zNear.
從而我們也就明白了,上面有個網(wǎng)頁上,把它比如成眼睛的睜開度,感覺有點牽強.
眼睛睜開度鏈接(有圖).
三、坐標系相關(guān)函數(shù)
計算機圖形學OpenGL中的glLoadIdentity、glTranslatef、glRotatef原理,用法 .(轉(zhuǎn)).
- OpenGL中的坐標用齊次坐標表示,即(x,y,z)表示成 (x’,y’,z’,h) ,其中x=x’/h; y=y’/h; z=z’/h. 通常h取1. 比如空間中的點(2,3,4),在OpenGL中將表示成(2,3,4,1). 齊次坐標表示方式適合于矩陣運算
- OpenGL有個變換矩陣堆棧,堆棧就像子彈夾一樣,先進的后出。OpenGL中的每個向量,在被定義之后進入到OpenGL世界中,都必須先乘以這個變換矩陣堆棧的棧頂變換矩陣。
- 使用glPushMatrix和glPopMatrix的組合可以隔離這兩個函數(shù)中的變換,使之不影響后面的點
變換坐標系的函數(shù)——glLoadIdentity()與glTranslatef()和glRotatef().
glLoadIdentity() 對應(yīng)單位陣,將當前的用戶坐標系的原點移到了屏幕中心:類似于一個復(fù)位操作
四、紋理坐標
Android OpenGL es 紋理坐標設(shè)定與貼圖規(guī)則.
OpenGL 紋理坐標 和 頂點坐標映射關(guān)系 詳解.
在繪制紋理映射場景時,不僅要給每個頂點定義幾何坐標,而且也要定義紋理坐標。經(jīng)過多種變換后,幾何坐標決定頂點在屏幕上繪制的位置,而紋理坐標決定紋理圖像中的哪一個紋素賦予該頂點。
- 紋理圖像是方形數(shù)組,紋理坐標通常可定義成一、二、三或四維形式,稱為s,t,r和q坐標,以區(qū)別于物體坐標(x, y, z, w)和其他坐標。一維紋理常用s坐標表示,二維紋理常用(s, t)坐標表示,目前忽略r坐標。q坐標像w一樣,一般情況下其值幾乎均為1,主要用于建立齊次坐標。
- 注意:對于任何紋理,無論紋理的真正大小如何,其頂端(左下角)的紋理坐標恒為(0,0),右上角的紋理坐標恒為(1,1)。也就是說,紋理坐標應(yīng)是一個介于0到1之間的一個小數(shù)。
紋理坐標和頂點坐標.
- 紋理坐標是從0到1,它的坐標是x向右,y向下
頂點坐標是從-1到-1,坐標是x向右,y向上
程序中坐標代碼可參考:android opengl播放全景視頻.
五、紋理過濾
紋理環(huán)繞方式給出了紋理坐標超出設(shè)置范圍外的視覺輸出效果。與之函數(shù)相似,有紋理過濾:
由于紋理坐標不依賴與分辨率,也就是說OpenGL如果將一張照片映射到一個很大的面上則會清晰地看到像素點,這時候過濾就顯得很重要了。
之前搞不清楚紋理過濾和glShadeModel,以為紋理過濾可有可無,它和glShadeModel好像意思差不多,看完下面這篇文章才更深入理解了
openGL ES 常用接口剖析.
(一)
紋理過濾是對應(yīng)著把紋理圖像映射成像素,
圖象從紋理圖象空間映射到幀緩沖圖象空間(映射需要重新構(gòu)造紋理圖像,這樣就會造成應(yīng)用到多邊形上的圖像失真),這時就可用glTexParmeteri()函數(shù)來確定如何把紋理象素映射成像素.
下面整理了紋理映射的基本步驟
具體紋理映射分為
- 指定紋理
- 控制紋理
控制紋理是控制紋理圖像的紋理如何對應(yīng)到屏幕上的像素,怎樣通過紋理貼圖實現(xiàn)紋理縮放和紋理重復(fù)等
glTexParmeteri() 就是來確定如何把紋理象素映射成像素 - 紋理對象
- 紋理函數(shù)
- 分配紋理坐標
用glTexCoord函數(shù)
(二)
而glShadeModel是說明兩頂點之間的象素怎么處理的。把參數(shù)設(shè)置成GL_SMOOTH,即啟用柵格化功能
在opengl流水線里頭,有一個步驟是柵格化(Rasterization),它在頂點組合的幾何信息處理后執(zhí)行,目的是“插值”,vertex shader的varying變量就是在這里被柵格化(插值),然后再傳入fragment shader作象素級別的處理。
六、深度緩沖區(qū)
OpenGL 深度緩沖區(qū) Z緩沖區(qū)介紹.
不考慮繪制的順序?qū)τ谕粋€像素遮擋的影響,啟用深度測試可以決定何時覆蓋或不覆蓋一個像素。
為了啟動深度緩沖區(qū),必須先啟動它,即glEnable(GL_DEPTH_TEST)。每次繪制場景之前,需要先清除深度緩沖區(qū),即glClear(GL_DEPTH_BUFFER_BIT),然后以任意次序繪制場景中的物體。
七、OpenGL的glut庫
glut庫是主要干什么的?
OpenGL中的gl,glu,glut的區(qū)別.
GLUT及其函數(shù)的用法整理.
回調(diào)函數(shù)就是一個通過函數(shù)指針調(diào)用的函數(shù)。如果你把函數(shù)的指針(地址)作為參數(shù)傳遞給另一個函數(shù),當這個指針被用來調(diào)用其所指向的函數(shù)時,我們就說這是回調(diào)函數(shù)。回調(diào)函數(shù)不是由該函數(shù)的實現(xiàn)方直接調(diào)用,而是在特定的事件或條件發(fā)生時由另外的一方調(diào)用的, 用于對該事件或條件進行響應(yīng)。
OpenGL函數(shù)功能glutTimerFunc()
OpenGL函數(shù)功能glutTimerFunc().
opengl之glutTimerFunc.(有代碼示例)
此函數(shù)用于刷新,具體用法如下:
glutTimerFunc(unsigned int millis, void (*func)(int value), int value);
參數(shù)對應(yīng)關(guān)系為:glutTimerFunc(毫秒數(shù), 回調(diào)函數(shù)指針, 區(qū)別值). 用value區(qū)分是哪個定時器
- 在函數(shù)里改變和位置有關(guān)的變量,然后調(diào)用glutPostRedisplay();用來重繪
- 最后再次調(diào)用glutTimerFunc,因為glut的定時器是調(diào)用一次才產(chǎn)生一次定時,所以如果要持續(xù)產(chǎn)生定時的話,在定時函數(shù)末尾再次調(diào)用glutTimerFunc
做鼠標拖動時可以借鑒:
OpenGL的幾何變換3之內(nèi)觀察全景圖
.
glutMainLoop()循環(huán)什么?
讓所有的與“事件”有關(guān)的函數(shù)調(diào)用無限循環(huán)。
參見
按照我的理解,是有兩個線程并行,main函數(shù)中是主線程,其中 glutDisplayFunc(display)實現(xiàn)繪制,而子線程是FFmpeg實現(xiàn)解碼,用緩沖區(qū)防止數(shù)據(jù)錯亂
總結(jié)
以上是生活随笔為你收集整理的全景视频播放器中OpenGL的相关记录的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【设计模式实战】SpringBoot模板
- 下一篇: 免费搭建属于自己的域名个性邮箱