1,隱喻
思考一下畫家繪畫的過程,首先要有一名懂得各種繪畫技藝的畫家,然后他需要一張畫布,一些筆,一些顏料,一些輔助工具(尺、圓規、模板、橡皮、調色板等等),然后他在畫布上繪制第一幅畫,完成之后展示給人們看;在人們觀賞第一幅畫的時候,他可以在第二張畫布上繪制第二幅畫,繪制完成后收回第一幅畫,將第二幅畫展現給人們看;接着使用工具擦除第一幅畫,在同一張畫布上繪制第三幅畫;周而復始,人們便看到了一幅接一幅的畫。
對比OpenGL ES,各要素的對應關系大體如下:
畫家:我們
筆、顏料、輔助工具:OpenGL ES API
畫布:???
2,畫布、像素、顯存
畫布是畫面的載體,而計算機圖形總是展現在屏幕的某個矩形范圍內,這個矩形就是其載體。我們用像素作為基本單位來描述這個矩形的大小,像素是屏幕顯示畫面的最小單位,可以近似的認為是一個有特定顏色特定大小(面積)的點。256 * 128表明這個矩形的長為256像素,高為128像素,這也是屏幕分辨率的定義(屏幕可視為一個最大的顯示矩形)。所謂繪制就是用不同顏色的像素填充矩形,矩形的本質是一塊內存(一般位於GPU上,稱為顯存),填充像素的本質就是向這塊內存寫入數據,這些數據描述了每個像素應該是什么顏色。(大部分顯示器上)計算機畫面最終都是作為像素點陣呈現的。
屏幕上一個10*10的矩形,對應着一塊10*10的顯存,總共有10*10 = 100個像素,那么這塊顯存有多大呢?這要看每個像素有多大,假設一個像素占用2個字節,那么顯示10*10矩形所需用到的顯存就是10*10*2=200字節。 如果一個像素占用4個字節,那么顯存大小就是10*10*4 = 400字節。
3,顏色
那么一個像素是如何描述某種特定的顏色的?有很多種方式,這里我們只談最通用的RGB顏色模型。
人眼所看到的顏色本質上是光子撞擊人眼產生,所有顏色都可以用RGB三原色(紅、綠、藍)按一定強度比例混合而成,顯示器屏幕所展現的各種顏色,是所有像素的集合,而每個像素都會發出RGB三種顏色混合的光,只要通過某種特定方式控制這三種顏色的比例和光的強度,就達到了控制顏色顯示的目的。
假設一個像素為兩個字節,我們可以給這個像素任意一個值,比如0x3826,最終硬件驅動將會解析這個數值,將其轉化為RGB的每個顏色分量的強度,按此激發屏幕像素,我們就看到了特定的一種顏色。因此這里需要有個約定,類似:0x1000代表100%的R,0%的G和B。這種約定稱之為像素(顏色)格式(Pixel/Color Format)。
Android中的像素格式在 PixelFormat類中描述,包括RGBA_8888,RGB_565等。這里的RGB_565表示每個像素有5個二進制位(bit)來表示R, 6 bits表示G,5 bits表示B,每個像素占用5+6+5 = 16 bits = 2字節。數值越大,表明對應的顏色(光)分量越強。比如:0x0000(RGB_565)代表沒有任何顏色,即黑色。
4,繪制
所以計算機繪畫的本質就是選擇一種像素格式,申請一塊顯存(畫布),填充像素(顏色),繪制完成之后,通知計算機顯示到屏幕上(按比例發射RGB光),最終就看到了所繪制的畫面。之所以要先選擇像素格式,是因為無論是所申請顯存的大小,還是硬件驅動解析顯存的方式,都是由像素格式決定的。
5,環境初始化
因此,在使用OpenGL ES繪制之前,所需要做的初始化工作就比較清晰了:
a, 選擇像素格式。
b, 申請顯存。
除此之外,還有一些初始化工作要做:
c, 選擇顯示設備(有些設備可能有不只一個顯示器);
d, 選擇某些特性,比如如果你打算畫中國水墨畫,你需要額外指定宣紙和毛筆。
e, 創建上下文(Context),上下文本質上是一組狀態的集合,描述了在某個特定時刻系統的狀態, 用於處理暫停、恢復、銷毀、重建等情況;
f, 指定當前的環境為繪制環境;比如你可能有多個環境,每個環境有不同參數,你需要在這些環境中切換(想象一下同時在兩個顯示器上繪制不同的畫面),所以必須指定當前的繪制環境。
完成上述所有工作之后,就可以開始使用OpenGL ES API進行繪制了(所有器具准備完畢,畫家開始作畫)。
6, EGL
由於像素格式、顯示設備這些涉及到硬件,不同系統之間可能差異很大(比如有的系統不支持RGB_565),維護OpenGL ES 的khronos組織使用一個專門的抽象層(想起了一句名言 - 某種意義上的冷笑話:所有的計算機問題都可以通過添加一個抽象層來解決)來處理不同系統間的適配,從而保證了OpenGL ES本身的平台無關性,這個抽象層就是EGL.
權威資料見這里:http://www.khronos.org/egl
EGL用來進行環境的初始化,包含了上面所描述的種種。
關於EGL的詳細說明將在下一篇文章中講述,以Android為例。