第一章 介紹opengles
OpenGL ES是一個應用程式設計介面(API),用於針對手機、個人數字助理(PDAs)、控制檯、電器、車輛和航空電子裝置等手持和嵌入式裝置的高階3D圖形。OpenGL ES是Khronos團隊建立的一套API之一。專注於為手持裝置和嵌入式裝置建立開放標準和免版稅的應用程式設計介面。
桌面世界有兩個標準的3D APIs,
- DirectX:是執行微軟視窗作業系統的任何系統的事實上的標準3D應用程式設計介面,被該平臺上的大多數3D遊戲使用。
- OpenGL是一個跨平臺的標準3D應用程式設計介面,適用於執行Linux、各種風格的UNIX、Mac OS X和微軟Windows的桌面系統。這是一個被廣泛接受的標準3D應用程式設計介面,在現實世界中得到大量使用。
簡單總結:opengles是一個程式設計的介面,用於手持裝置。桌面版有兩個3D的api,一個是opengl一個是directX。
由於OpenGL作為3D API的廣泛採用,在為手持和嵌入式裝置開發開放標準3D API並對其進行修改以滿足手持和嵌入式裝置空間的需求和限制時,從桌面OpenGL API開始是有意義的。OpenGL ES解決的裝置非常有限的處理能力和記憶體可用性、低記憶體頻寬、對電源的敏感性的限制。
- OpenGL API非常大且複雜,OpenGL ES工作組的目標是建立一個適用於受限裝置的API。為了實現這個目標,工作組從OpenGL API中移除了任何冗餘。在任何情況下,如果執行相同操作的方式不止一種,則採用最有用的方法,並刪除冗餘技術。一個很好的例子是指定幾何圖形,在OpenGL中,應用程式可以使用立即模式、顯示列表或頂點陣列。在OpenGL ES中,只有頂點陣列存在,即時模式和顯示列表被刪除
- 消除冗餘是一個重要的目標,但保持與OpenGL的相容性也很重要。OpenGL ES的設計儘可能地使那些被寫入OpenGL中嵌入式功能子集的應用程式也能在OpenGL ES上執行。這是一個重要目標的。原因是,它允許開發人員利用兩個應用程式設計介面,並開發使用公共功能子集的應用程式和工具。雖然這是一個重要的目標,但也有偏離的情況,尤其是OpenGL ES 2.0。這將在後面的章節中詳細討論。
- 引入了新功能來解決手持裝置和嵌入式裝置的特定限制。例如,為了降低功耗和提高著色器的效能,在著色語言中引入了精度限定符。
- OpenGL ES的設計者旨在確保影象質量的最小特徵集。大多數手持裝置的螢幕尺寸有限,因此螢幕上繪製的畫素質量必須儘可能好。
- OpenGL ES工作組希望確保任何OpenGL ES實現都將滿足某些可接受的和一致同意的影象質量、正確性和魯棒性標準。這是通過開發適當的一致性測試來實現的,OpenGL ES實現必須通過這些測試才能被認為是相容的。
簡單總結:
opengl是一個跨平臺的圖形程式設計API,使用在手持裝置上會因為顯示螢幕或者是記憶體,電量等因素的影響,所以就出現了opengles,
1.使用了最有效的繪製方式進行繪製
2.在不影響繪製質量的前提下刪除掉了冗餘的技術
3.引入了精度限制
4.繪製質量會盡量的好
5.具有良好的相容性。
OpenGL ES 2.0規範實現了一個可程式設計的圖形流水線,是從OpenGL 2.0規範衍生而來的。源自OpenGL規範的修訂意味著相應的OpenGL規範被用作確定OpenGL ES的特定修訂中的特徵集的基線。然後建立了一個不同的規範,描述了OpenGL ES相對於其派生的OpenGL規範的變化和增加。
OpenGL ES 2.0實現了一個可程式設計著色的圖形管道,由兩個規範組成:OpenGL ES 2.0 API規範和OpenGL ES著色語言規範(OpenGL ES SL)。圖1-1展示了OpenGL ES 2.0圖形流水線。圖中的陰影框表示OpenGL ES 2.0中流水線的可程式設計階段。概述
描述各個階段的概述
頂點著色器
頂點著色器實現了頂點進行操作的通用可程式設計方法。
頂點著色器的輸入包括以下內容:屬性、uniform、取樣器、著色器程式、可變變數
- Attributes—使用頂點陣列提供的每個頂點的資料
- Uniforms-頂點著色器使用的恆定資料。
- Samplers-代表頂點著色器使用的紋理的特定製服型別。頂點著色器中的取樣器是可選的。
- Shader program-頂點著色器程式原始碼或可執行檔案,描述將在頂點上執行的操作。(在我的使用過程中使用很少)
- 頂點著色器的輸出稱為可變變數。在圖元光柵化階段,為每個生成的片段計算變化的值,並將其作為輸入傳遞給片段著色器。用於從分配給圖元的每個頂點的變化值為每個片段生成變化值的機制稱為插值。頂點著色器的輸入和輸出如圖1-2所示。
頂點著色器可用於傳統的基於頂點的操作,如通過矩陣變換位置、計算光照方程以生成逐頂點顏色,以及生成或變換紋理座標。或者,因為頂點著色器是由應用程式指定的,所以頂點著色器可用於進行自定義頂點變換。
示例1-1顯示了一個用OpenGL ES著色語言編寫的頂點著色器。我們將在本書後面詳細解釋頂點著色器。我們現在展示這個著色器,只是為了讓您瞭解頂點著色器是什麼樣子的。示例1-1中的頂點著色器將位置及其相關的顏色資料作為輸入屬性,通過4 × 4矩陣轉換位置,並輸出轉換後的位置和顏色
Example 1-1 A Vertex Shader Example
示例 1-1 頂點著色器示例
1. // uniforms used by the vertex shader 固定值 是不會變化
2. uniform mat4 u_mvpMatrix; //描述了儲存組合模型檢視和投影矩陣的統一變數u_mvpMatrix。
5. // attributes input to the vertex shader 屬性值 是可以進行變化的(也就是可以傳遞進來的值)
6. attribute vec4 a_position; // position value
7. attribute vec4 a_color; // input vertex color
9. // varying variables – input to the fragment shader
10. varying vec4 v_color; // output vertex color 值傳輸給片段著色器 計算每一個點的值
12. void
13. main()
14. {
15. v_color = a_color;
16. gl_Position = u_mvpMatrix * a_position;
17.}
簡單總結:介紹可程式設計管線第一個可以控制的地方。頂點著色器,它可以有四種方式的輸入,一鍾方式的輸出,將資料傳遞給片元著色器。
圖元裝配
頂點著色器之後,管道中的下一個階段是圖元裝配。圖元是一種幾何物件,可以使用OpenGL ES中適當的繪製命令來繪製。這些繪圖命令指定一組頂點屬性,這些屬性描述圖元的幾何圖形和圖元型別。每個頂點都用一組頂點屬性來描述。這些頂點屬性包含頂點著色器用來計算位置的資訊以及可以傳遞給片段著色器的其他資訊,如其顏色和紋理座標。
簡單總結:就是將上一個階段的頂點,組合成為一個完整的圖形,比如三角形,直線。
在圖元組裝階段,著色頂點被組裝成可以繪製的單個幾何圖元,如三角形、直線或點精靈。對於每個圖元,必須確定圖元是否位於視平截頭體(螢幕上可見的3D空間區域)內。如果圖元沒有完全位於檢視平截頭體內部,則可能需要將圖元裁剪到檢視平截頭體上。如果圖元完全在外部,則被丟棄。裁剪後,頂點位置轉換為螢幕座標。還可以執行剔除操作,根據圖元是面向前還是面向後來丟棄圖元。在裁剪和剔除之後,圖元準備好被傳遞到管道的下一階段,即光柵化階段。
簡單總結:圖元會判斷是不是在視錐體的裡面,如果不在就需要進行一次裁剪,不在視錐體裡面的就需要將其刪除掉,還有需要執行剔除,根據設定的正向和反向來確定是不是需要剔除。
光柵化
圖1-3所示的下一個階段是光柵化階段,在此階段繪製適當的圖元(點精靈、線或三角形)。光柵化是將圖元轉換成一組二維片段的過程,這些片段由片段著色器處理。這些二維片段代表可以在螢幕上繪製的畫素。
簡單總結:就是將圖元使用一個二維陣列來進行顯示,每個陣列的點就代表這裡的畫素值。
片段著色器
片段著色器為光柵化階段的每一個片段執行
- 可變變數-由光柵化單元使用插值為每個片段生成的頂點著色器的輸出。
- uniforms-片段著色器使用的恆定資料。
- 取樣器——代表片段著色器使用的紋理的特定製服型別。
- 著色器程式—片段著色器程式原始碼或可執行檔案,描述將對片段執行的操作。
片段著色器可以丟棄片段,也可以生成一個稱為gl_FragColor的顏色值。由光柵化階段生成的顏色、深度、模板和螢幕座標位置(xw,yw)成為OpenGL ES 2.0管道的每個片段操作階段的輸入。
對於影象顯示的操作就在這裡,這裡可以對gl_color對應的就是每一個畫素點。
Example 1-2 A Fragment Shader Example
1. precision mediump float;
2. varying vec4 v_color; // input vertex color from vertex shader
3. void
4. main(void)
5. {
6. gl_FragColor = v_color;
7.}
- 第1行設定預設精度限定符(手持裝置的記憶體限制)
這將在第4章“著色器和程式”中詳細解釋第3行描述了片段著色器的輸入。頂點著色器必須寫入片段著色器讀取的同一組可變變數。 - 第6-10行描述了片段著色器的主要功能。請注意,片段著色器中沒有宣告輸出。這是因為唯一的輸出變數是gl_FragColor,在本例中,它被設定為第9行中v_color給定的片段著色器的輸入顏色。
每個片段進行操作
在片段著色器之後,下一個階段是每片段操作。用(xw,yw)螢幕座標光柵化產生的片段只能修改幀緩衝區中位置(xw,yw)處的畫素。圖1-5描述了OpenGL ES 2.0每片段操作階段。
簡單理解一下:就是一個二維陣列,每個畫素就代表一個二維陣列的值,在處理的過程裡面,每一個片段的操作只能處理對應x,y螢幕座標的裡面的畫素。
- 每一個片段進行哪些操作
- 畫素所有權測試:x,y中位置的畫素是否輸出當前上下文,就是要顯示的 。
- 剪式裁剪:剪式矩陣內就顯示 ,不在就不顯示
- 模板測試和深度測試:對傳入的值進行測試
- 混合:將儲存在裡面的值和當前的顏色值想結合
- 抖動:抖動可用於最大限度地減少因使用有限精度在幀緩衝區中儲存顏色值而產生的偽像
測試結束要不就將值寫入要不就直接丟棄,取決於掩碼的值。還有一個可以從快取區中讀取資料的介面。
EGL
OpenGL ES命令需要一個渲染上下文和一個繪圖表面。渲染上下文儲存適當的OpenGL ES狀態。繪圖表面是圖元將被繪製到的表面。繪圖表面指定渲染所需的緩衝區型別,如顏色緩衝區、深度緩衝區和模具緩衝區。繪圖面還指定了每個所需緩衝區的位深度。
(surfaceView和GLSurfaceView就會看到這個EGL.)
OpenGL ES API沒有提到渲染上下文是如何建立的,或者渲染上下文是如何附加到本機視窗系統的。EGL是OpenGL ES等Khronos渲染APIs和原生視窗系統之間的一個介面。實現OpenGL ES時不需要提供EGL。開發人員應該參考平臺供應商的文件來確定支援哪個介面。
在開始渲染之前,任何OpenGL ES應用程式都需要使用EGL執行以下操作:
- 查詢裝置上可用的顯示並初始化它們。例如,一個翻蓋手機可能有兩個液晶面板,我們可以使用OpenGL ES渲染可以在其中一個或兩個面板上顯示的表面。
- 建立渲染表面。在EGL建立的表面可以分為螢幕表面和螢幕外表面。螢幕上的表面被附加到本地視窗系統,而螢幕外的表面是畫素緩衝區,不被顯示,但可以用作渲染表面。這些表面可用於渲染成紋理,並可在多個Khronos APIs之間共享。
- 建立渲染上下文。需要EGL來建立一個OpenGL ES渲染上下文。在實際開始渲染之前,需要將此上下文附加到適當的表面上。
EGL應用程式設計介面實現了剛才描述的特性和附加功能,如電源管理、支援一個程序中的多個渲染上下文、在一個程序中的渲染上下文之間共享物件(如紋理或頂點緩衝區),以及獲取給定實現支援的EGL或OpenGL ES擴充套件函式的函式指標的機制。EGL規範的最新版本是EGL版本1.4。
重新整理和完成
OpenGL ES 2.0 API繼承了OpenGL客戶端-伺服器模型。應用程式或客戶端發出命令,這些命令由OpenGL ES實現或伺服器處理。在OpenGL中,客戶機和伺服器可以通過網路駐留在不同的機器上。OpenGL ES還允許客戶端和伺服器駐留在不同的機器上,但是因為OpenGL ES的目標是手持和嵌入式平臺,所以客戶端和伺服器通常在同一臺裝置上。
在客戶機-伺服器模型中,客戶機發出的命令不一定會立即傳送到伺服器。如果客戶機和伺服器在網路上,那麼通過網路傳送單獨的命令將會非常低效。相反,命令可以在客戶端緩衝,然後在稍後的時間點發送到伺服器。因此,需要有一種機制,讓客戶機知道伺服器何時完成了以前提交的命令的執行。考慮另一個例子,其中多個OpenGL ES上下文(每個當前到不同的執行緒)共享物件。為了在這些上下文之間正確同步,來自上下文A的命令在依賴於由上下文A修改的OpenGL ES狀態的上下文B之前被髮布到伺服器是很重要的。glFlush命令用於重新整理當前OpenGL ES上下文中的任何未決命令,並將它們釋出到伺服器。請注意,glFlush只向伺服器發出命令,不等待它們完成。如果客戶端要求完成命令,應該使用glFinish命令。但是,除非絕對必要,否則我們不建議使用glFinish。因為在伺服器完全處理完上下文中所有排隊的命令之前,glFinish不會返回,所以呼叫glFinish會強制客戶端和伺服器同步它們的操作,從而對效能產生不利影響。
總結:
兩大3D渲染API,一個是DirectX和open gl,前一個執行在微軟各個平臺,後者可以在多個平臺執行,open gles是面對手持裝置上的,由於手持裝置的各種侷限,所以在opengles對opengl進行了一些冗餘處理,但是也需要保持高度的相容性,並且opengles可以設定資料型別。
目前主要的版本包括1.0和2.0,主要區別是固定管線和自定義管線,因為種種原因它是不可以向後相容的(需要更小的儲存,使用者反饋),opengles是通過opengl衍生而來的,它主要可以控制片元著色器和著段找色器,片元著色器主要有屬性、uniform、取樣器、著色器程式、可變變數(varing),主要的操作有進行座標變換的處理,光照計算。可變變數作為一種輸出,可以傳遞給片段找色器,在柵格化階段計算出顏色的插值。頂點找色器的資料一般會進入到圖元裝配階段,圖元裝配的作用是將頂點變化為基本的圖元,被繪製成點線三角形,點的位置還會進行一次判斷,是否在視屏接頭內部,不在的將會被拋棄,然後進入到下一個階段柵格化階段,柵格化就是將上一部分的資料進行一次處理,變為一個座標點,也可以認為是畫素點,並且也會計算插值。下一步就是片段著色器,它為光柵化後的每一個片段進行執行,它有可變變數,取樣器,著色器程式,這裡可以丟棄片段,也可以設定glColor,光柵化階段生成的顏色、深度、魔板。螢幕座標位置成為每個片段操作的輸入。下來就是沒片段進行執行,光柵化階段的片段只可以修改緩衝區中的畫素,每個片段都會執行以下操作:畫素測試(是否屬於我的標準是否被遮擋)、裁剪矩形、深度測試、混合操作、消除抖動。
EGL是顯示錶面和opengl聯絡的中間部分,顯示錶面是顯示屏,opengl狀態是繪製資料的狀態
執行的一個基本順序,載入頂點座標,然後變化到本地記憶體區域(java 程式碼需要)、頂點找色器的處理、圖元處理,柵格化、片段找色器、畫素 測試、矩陣裁剪、深度測試。混合測試、消除抖動。
重新整理和完成,重新整理是執行完成 之後的執行的一種客戶端的重新整理操作,完成是執行的一種強制操作,即使沒有操作完成也會執行的重新整理操作。
狀態機:本次設定,如果不進行修改下次操作仍然使用這個操作。