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