khronos官方對OpenGL ES的描述如下:
OpenGL? ES is a royalty-free, cross-platform API for rendering advanced 2D and 3D graphics on embedded and mobile systems - including consoles, phones, appliances and vehicles. It consists of a well-defined subset of desktop OpenGL suitable for low-power devices, and provides a flexible and powerful interface between software and graphics acceleration hardware.
OpenGL ES 是一種免費的跨平臺 API,用于在嵌入式設備和移動系統(包括 consoles、手機、電器 和 車載 )上渲染高效的 2D 和 3D 圖形, OpenGL ES 由OpenGL裁剪而來,適用于低功耗設備,并為軟體和圖形硬體加速之間提供靈活而強大的介面,
這篇文章主要介紹OpenGL ES的渲染流程,通過該文章了解一幀影像經過OpenGL ES處理,是如何最終渲染到手機螢屏上的,
二、著色語言
OpenGL ES 2.x采用的是可編程渲染管線(OpenGL ES 1.x為固定渲染管線),將頂點著色器、片元著色器的編碼權限開放給開發者,
開發者需要使用OpenGL ES Shading Language(著色語言) 編碼實作頂點著色器、片元著色器處理邏輯,從而渲染出自己想的展示效果,
正文開始之前,有必要先了解一下OpenGL ES 與 OpenGL ES Shading Language 的對應關系,了解對應的API版本,才能撰寫對應版本要求的Shading Language腳本,
| OpenGL ES Version | GLSL Version |
|---|---|
| 1.0 | -- |
| 1.1 | -- |
| 2.0 | 100 |
| 3.0 | 300 |
| 3.1 | 310 |
| 3.2 | 320 |
- OpenGL ES 1.x為固定渲染管線,無Shading Language對應版本;
- OpenGL ES 2.x開始才有可編程渲染管線,
OpenGL ES 2.0對應的OpenGL ES Shading Language版本為1.00
Shading Language 1.00 檔案:
https://www.khronos.org/registry/OpenGL/specs/es/2.0/GLSL_ES_Specification_1.00.pdf
各OpenGL ES版本API檔案:
https://www.khronos.org/registry/OpenGL/specs/es/
二、渲染管線
OpenGL ES中的渲染管線指的是一系列的繪制程序,輸入是需要渲染的3D物體的相關描述資訊資料(例:頂點坐標、頂點顏色、頂點紋理等),經過渲染管線,輸出一幀想要的影像,
渲染管線也稱之為渲染流水線,由顯示芯片(GPU)內部處理圖形信號的并行處理單元組成,這些并行處理單元兩兩之間相互獨立,根據顯示芯片性能的不同處理單元的數量也存在很大的差異,將渲染作業通過顯示芯片中多個相互獨立的單元進行并行處理后,渲染的效率可以大大提高,
OpenGL ES 2.x的渲染管線如下圖所示:

2.1 基本處理
該階段設定三維空間中物體的頂點坐標、頂點對應的顏色、頂點的紋理坐標等資料,并且指定三維物體的繪制方式,如:點繪制、線段繪制或者三角形繪制等,
2.2 頂點緩沖區
頂點緩沖區在應用程式中是可選的,對于某些在整個場景中頂點資料基本不變的情況,可以在初始化階段將頂點資料經基本處理后送入頂點緩沖區,在繪制每一幀想要的影像時就省去了頂點資料IO的步驟,直接從頂點緩沖區中獲取頂點資料即可,相比于每次繪制時單獨將頂點資料送入GPU的方式,可以在一定程度上節省GPU的 IO 帶寬,提高渲染效率,
2.3 頂點著色器
頂點著色器是一個可編程的處理單元,功能為執行頂點的變換、光照、材質的應用與計算等頂點的相關操作,每個頂點執行一次,
其作業程序為將原始的頂點幾何資訊(頂點坐標、顏色、紋理)及其他屬性傳送到頂點著色器中,經過自定義的頂點著色程式處理產生變化后的頂點位置資訊,將變化后的頂點位置資訊傳遞給后續圖元裝配階段,對應的頂點紋理、顏色等資訊則經光柵化后傳遞到片元著色器,
頂點著色器替代了原有固定管線(OpenGL 1.x采用固定渲染管線)的頂點變換、光照計算,采用 著色語言進行開發(OpenGL ES Shading Language) ,開發人員可以根據自己的需求采用著色語言自行開發頂點變換、光照等功能,大大增加了程式的靈活性,

頂點著色器的輸入主要為待處理頂點相應的attribute、uniform、采樣器以及臨時變數,輸出主要為經過頂點著色器后生成的varying及一些內建輸出變數,
uniform(統一變數):
指的是對于同一組頂點組成的三維物體其所有頂點屬性都相同的屬性量,一般為場景中當前的光源位置、當前的攝像機位置、投影系列矩陣等,,可以使用 uniform (統一變數) 傳入頂點著色器,attribute(屬性變數)
指的是三維空間中物體每個頂點各自不同的資訊所屬的變數,一般為頂點的位置、顏色、法向量等,每個頂點各自不同的資訊都是以attribute變數的方式傳入頂點著色器的,varying(易變變數)
對于從頂點著色器傳遞到片元著色器的量,如 用于傳遞到片元著色器中的頂點顏色,可以使用varying (易變變數),- gl_Position (內建變數):
內建變數為輸出到OpenGL ES渲染管線的資料變數,
頂點著色器從應用程式中獲得原始的頂點位置資料,這些原始的頂點資料在頂點著色器中經過平移、旋轉、縮放等數學變換后,生成新的頂點位置,新的頂點位置通過在頂點著色器中寫入gl_Position傳遞到渲染管線的后繼階段繼續處理, - gl_PointSize (內建變數):
內建變數為輸出到OpenGL ES渲染管線的資料變數,
gl_PointSize的值一般只有在采用了點繪制方式之后才有意義,頂點著色器中可以計算一個點的大小(單位為像素),并將其賦值給gl_PointSize(float型別)以傳遞給渲染管線,如果沒有明確賦值的話,默認值為1,
頂點著色器代碼舉例
著色器采用OpenGL ES Shading Language撰寫,為一種類C的編程語言,頂點著色器代碼實作舉例如下:
詳細了解著色語言語法,可查看khronos官方:
OpenGL ES Shading Language 1.00:
https://www.khronos.org/registry/OpenGL/specs/es/2.0/GLSL_ES_Specification_1.00.pdf
// 頂點著色器程式舉例如下:
uniform mat4 uMVPMatrix; //總變換矩陣
attribute vec3 aPosition; //頂點位置
attribute vec4 aColor; //頂點顏色
varying vec4 vColor; //用于傳遞給片元著色器的變數
void main()
{
//根據總變換矩陣計算此次繪制此頂點位置
gl_Position = uMVPMatrix * vec4(aPosition,1);
//將接收的顏色傳遞給片元著色器
vColor = aColor;
}
uniform(統一變數)
如:頂點著色器舉例程式中的uniform mat4 uMVPMatrix; 總變換矩陣,attribute(屬性變數)
如:頂點著色器舉例程式中的頂點位置aPosition、頂點顏色aColor,varying(易變變數)
如:頂點著色器舉例程式中的varying vec4 vColor; 頂點顏色,內建輸出變數
如:如輸出到渲染管線的 gl_Position(頂點的最終位置),
注:
易變變數(頂點顏色、紋理)在頂點著色器賦值后并不直接賦值到片元著色器中,而是經由光柵化階段處理,將三維世界由頂點資料構成的物體離散為二維世界一個個像素點,片元著色器處理的資料是已經離散到二維顯示平面上的一個個離散的像素點(每個像素點為一個片元),而這個離散程序中位于兩個頂點之間的像素頂資料(顏色值、紋理資料),大多在光柵化階段差值計算產生,

上圖中,展示的是一個自上而下從黑到白的一個漸變三角形,
在OpenGL ES的輸入中,僅僅輸入了三個頂點顏色值,頂點1 (0,0,0) 黑色、,頂點2 (1,1,1) 白色、頂點3 (1,1,1) 白色,而在三角形在光柵化階段,投影到螢屏上之前,其他部分的顏色是由這三個輸入頂點顏色值差值計算產生的,例如:三角形高二分之一處的點顏色差值計算的結果為 (0.5,0.5,0.5) 灰色,
2.4 圖元裝配
在這個階段,主要有兩個任務,一個是圖元組裝,另一個是圖元處理,
圖元組裝是頂點資料被結合成完整的圖元,
例如:一個單獨的點就是一個圖元,它只需要一個點;一條直線也是一個圖元,為兩個點構成的圖元;三角形則需要三個頂點構成一個圖元,
圖元組裝時會有效的收集足夠的頂點以組成一個單獨的圖元,方便進行后續處理,圖元處理最重要的是剪裁,其任務是消除位于顯示區域之外的部分幾何圖元,
圖元處理階段:
如果圖元完全位于視椎體內,則傳遞圖元進行后面的處理;
如果有一部分位于視椎體內,則剪裁該圖元(剪裁圖元可能會額外增加頂點資料),
如果其完全位于視椎體外,則丟棄該圖元,以節省GPU性能,

2.5 光柵化
光柵化就是將三維空間中連續的數學圖形,柵格化為二維顯示平面上一個個像素點的程序,
將由三維頂點資訊組成的幾何圖元,柵格化為幀緩沖區中由無數像素點構成的二維影像,這里,最終生成的幀緩沖區中每一個像素點都被看做一個片元,
例如,一條直線可能在螢屏上包含了5個像素,而光柵化就是將這條直線轉化為5個片元,每個片元由頂點坐標、頂點顏色、頂點紋理坐標以及頂點的深度等資訊組成,
光柵化實際是由以下兩個程序組成:
- 將三維空間中的幾何圖元,投影到二維平面上:

- 將投影到二維平面上的幾何圖元,柵格化為幀緩沖區中一個個像素:

2.6 片元著色器
片元著色器是用于處理片元相關資料的可編程單元,可以執行紋理的采樣、顏色的匯總、計算霧顏色等操作,每片元執行一次(每個像素執行一次),
片元著色器可編程單元替換了OpenGL ES 1.x固定渲染管線階段中紋理顏色求和、霧以及Alpha測驗等階段,被其替代的功能將需要由開發人員用著色器語言編碼完成,

頂點著色器每頂點執行一次,片元著色器每片元[像素]執行一次,
一般情況下片元的數量遠遠大于構成三維物體頂點的數量(例如:一個三角形由三個頂點資料構成,光柵化到螢屏上時,卻有成百上千個像素點構成),因此片元著色器的執行次數明顯大于頂點著色器的執行次數,開發中為提高運行效率,應盡量減小片元著色器的運算量,將一些復雜運算放在頂點著色器中執行,
varying(易變變數)
從頂點著色器傳遞到片元著色器的資料變數,如頂點著色器所介紹,由系統在頂點著色器后的光柵化階段自動插值產生,varying變數個數隨需求而定,并沒有硬性的變數數量上限限制,- gl_FragColor (內建變數):
片元著色器用 gl_FragColor 向OpenGL ES渲染管線寫入計算完成的片元顏色值,此顏色值將進入渲染管線的后繼階段繼續處理,
片元著色器代碼舉例
著色器采用OpenGL ES Shading Language撰寫,為一種類C的編程語言,片元著色器代碼實作舉例如下:
詳細了解著色語言語法,可查看khronos官方:
OpenGL ES Shading Language 1.00:
https://www.khronos.org/registry/OpenGL/specs/es/2.0/GLSL_ES_Specification_1.00.pdf
// 片元著色器舉例(每個片元[像素]執行一次)
precision mediump float;
//接收從頂點著色器過來的引數(具體數值由光柵化階段差值產生)
varying vec4 vColor;
void main()
{
//片元的最終賦值
gl_FragColor = vColor;
}
varying(易變變數)
例,接收從頂點著色器過來的顏色引數varying vec4 vColorgl_FragColor
例,片元著色器具體程式中的gl_FragColor = vColor,
2.7 剪裁測驗
如果程式中啟用了剪裁測驗,OpenGL ES 會檢查每個片元在幀緩沖中對應的位置,若對應位置在剪裁視窗中則將此片元送入下一階段,否則丟棄此片元,,
2.8 深度測驗和模板測驗
- 深度測驗
- 模板測驗
a、深度測驗
深度測驗是在片元處理程序中通過測驗一個片元在視椎體的深度坐標,來判斷它是否被更小深度坐標的片斷遮擋而決定是否真去繪制它(開啟深度測驗有助于節省GPU性能);沒有深度測驗,物體展現與否就會取決于繪制順序而不是擺放的坐標,
// 在Android中打開深度測驗
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
b、模板測驗
模板測驗的主要功能為將繪制區域限定在一定的范圍內,一般用在湖面倒影、鏡像等場合,
模板測驗涉及到一個詞模板緩沖區(Stencil Buffer),在模板緩沖中,通常每個模板值(Stencil Value)是8位的,所以每個片元一共能有256種不同的模板值,
使用時,我們可以先將模板緩沖區刷成個某個固定的值,然后進行影像繪制,完成繪制后模板緩沖區中的值可能會被污染[污染],此時開發者就可以選擇丟棄或是保留這些被污染的片段,從而構造湖面倒影或者鏡像,
2.9 顏色緩沖混合
經過前面的幾個階段,已經產生了候選片元,而候選片元最終要進入幀緩沖成為像素,
在候選片元進入幀緩沖區成為像素的程序中:
- 若未開啟了Alpha混合,則當前片元成為螢屏的像素,覆寫掉螢屏上的原有像素;
- 若開啟了混合,則根據Alpha值將當前像素與候選片元進行顏色混合得出最終的顏色,
2.10 抖動
抖動是一種簡單的操作,是一種在色彩空間較小的設備上展示較大色彩空間的影像的一種方法,
例如:在一個RGB_565的設備上展示RGB_888的影像,展示時如果簡單進行資料截斷位,會造成色彩的失真和生硬,抖動使用一個矩陣,來調整一個像素周圍的像素的值,來使人眼產生錯覺,而模擬出原來的色彩,
這種技巧,對于只支持8位或者16位顏色資訊的顯示系統中非常有用,
// 開啟抖動
GLES20.glEnable(GLES20.GL_DITHER);
2.11 幀緩沖
OpenGL ES的物體繪制并不是直接回執在螢屏上的,而是預先在幀緩沖區中進行繪制,每一繪制完成一幀再將繪制的結果交換到螢屏上,因此,每次繪制新的一幀資料時都需要清理緩沖區中的相關資料,否則可能產生錯誤的顯示效果,
三、參考
OpenGL ES Shading Language 1.00:
https://www.khronos.org/registry/OpenGL/specs/es/2.0/GLSL_ES_Specification_1.00.pdf
OpenGL ES 2.0 API:
https://www.khronos.org/registry/OpenGL-Refpages/es2.0/
= THE END =

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/296165.html
標籤:其他
上一篇:OpenCV 之 自定義濾波
下一篇:基于樣例的傳統影像修補演算法實作
