OpenGLES渲染管道,頂點著色器(VertexShader) ,片元著色器(FragmentShader)

著色器只能用在OpenGLES 2.X以上等可編程管道里,而在OpenGLES 1.X是不能使用的。

管線,Pipeline,顯卡執行的、從幾何體到最終渲染圖像的、數據傳輸處理計算的過程

OpenGLES1.X中它是固定管道,整體式封閉的,中間的各道工藝按固定的流程順序走。如圖所示:

從上圖可以看出,這些工藝順序是固定的,整個過程又分為:處理頂點,處理片元,驗證片元信息并存入內存

Rasterizer:光柵化處理,當頂點處理完,會交給rasterizer來進行光柵化處理,結果會吧頂點的坐標信息轉換成能在屏幕顯示的像素信息,即片元(Fragments)

生成片元后,接下來就是對fragments片元的各種驗證,即過濾掉無用的片元,裁剪掉不在視野內的片元,最終把有效片元存儲入內存中。

光柵化處理過程,就是把矢量圖轉化成像素點的過程。我們屏幕上顯示的畫面都是由像素組成,而三維物體都是點線面構成的。要讓點線面變成能在屏幕上顯示的像素,就需要Rasterizer這個過程。

OpenGLES2.X可編程管道,由兩VertexShader(頂點著色器)、FragmentsShader(片元著色器)組成,分別對應上圖中的Coordinates 和Texture等藍色塊

OpenGLES2.0可渲染管道圖:

VertexShader:頂點著色器

頂點著色器輸入包括:

著色器程序——描述頂點上執行操作的頂點著色器程序源代碼或者可執行文件

頂點著色器輸入(或屬性)——用頂點數組提供的每個頂點的數據

統一變量(uniform)——頂點(或片段)著色器使用的不變數據

采樣器——代表頂點著色器使用紋理的 特殊統一變量類型

頂點著色器的輸出在OpenGLES2.0稱作可變變量(varying),但在OpenGLES3.0中改名為頂點著色器輸出變量。

在光柵化階段,為每個生成的片段計算頂點著色器輸出值,并作為輸入傳遞給片段著色器。

插值:光柵器對從頂點著色器傳遞的變量進行插值

為了在屏幕上真正顯示,必須將頂點著色器vs的輸出變量設置為gl_Position,gl_Position是一個保存著頂點齊次坐標的4維向量。ZYZ分量被W分量分割(稱作視角分割)并且XYZ分量上超過單位化盒子([-1, 1])的部分會被裁剪掉。最終的結果會被轉換到屏幕坐標系然后三角形(或其它圖元類型)被光柵器生成對應的像素。

OpenGLES3.0新增了一個功能——變換反饋,使頂點著色器輸出可以選擇性地寫入一個輸出緩沖區(除了傳遞給片段著色器之外,也可用這種傳遞替代)

頂點著色器的輸入和輸出如下圖所示:

先看看腳本:

private final String mVertexShader =

"uniform mat4 uMVPMatrix;\n" +

"attribute vec4 aPosition;\n" +

“attribute vec4 a_color;\n” +

"attribute vec2 aTextureCoord;\n" +

"varying vec2 vTextureCoord;\n” +

“out vec4 v_color;\n"

"void main() {\n" +

" gl_Position = uMVPMatrix * aPosition;\n" +

"?vTextureCoord = aTextureCoord;\n" +

“ v_color = a_color;\n"

"}\n";

private final String mFragmentShader =

"precision mediump float;\n" +

"varying vec2 vTextureCoord;\n" +

"uniform sampler2D sTexture;\n" +

"void main() {\n" +

"gl_FragColor = texture2D(sTexture, vTextureCoord);\n” +

"}\n”;

其中腳本語句關鍵字:

attribute:使用頂點數組封裝每個頂點的數據,一般用于每個頂點都各不相同的變量,如頂點位置、顏色等

uniform:頂點著色器使用的常量數據,不能被著色器修改,一般用于對同一組頂點組成的單個3D物體中所有頂點都有相同的變量,如當前光源位置

sampler:這是可選的,一種特殊的uniform,表示頂點著色器使用的紋理

mat4:表示4x4浮點數矩陣,該變量存儲了組合模型視圖和投影矩陣

vec4:表示包含了4個浮點數的向量

varying:用于從頂點著色器傳遞到片元或FragmentsShader傳遞到下一步的輸出變量

uMVPMatrix * aPosition:通過4x4 的變換位置后,輸出給gl_Position,gl_Position是頂點著色器內置的輸出變量。

gl_FragColor:片元著色器內置的輸出變量

PrimitiveAssembly:圖元裝配

圖元即圖形,在OpenGL有幾個基本圖元:點、線、三角形,其他的復雜圖元都是基于這些基本圖元來繪制而成。

在圖元裝配階段,那些經過頂點著色器(VertexShader)處理過的頂點數組或緩沖區的數據(VertexArrays/BufferObjects),被組裝到一個個獨立的幾何圖形中(點,線,三角形)

對裝配好的沒個圖元,都必須確保它在世界坐標系中,而對于不在世界坐標系中的圖元,就必須進行裁剪,使其處于在世界坐標系中才能流到下一道工序(光柵化處理)

這里還有一個剔除操作(Cull),前提是這個功能的開關是打開的:GLES20.glEnable(GLES20.GL_CULL_FACE); 剔除的是圖元的背影,陰影,背面等。

Rasterization:光柵化

光柵化階段繪制對應的圖元(點、線、三角形),將圖元轉化為一組二維數組的過程,然后傳遞給片段著色器處理。這些二維數組代表屏幕上繪制的像素

(PS:上圖中的點精靈光柵化應該是點光柵化)

FragmentShader:片元著色器

片元著色器主要是對光柵化處理后生成的片元逐個進行處理。接收頂點著色器輸出的值,需要傳入的數據,以及它經過變換矩陣后輸出值存儲位置。

著色器程序——描述片元所執行的片元著色器程序源代碼

輸入變量——光柵器對頂點著色器插值后的輸出值

統一變量——片元(或頂點)著色器使用的不變的數據

采樣器——代表片元著色器所用紋理的一種特殊的統一變量類型

片元著色器輸入和輸出關系如下圖所示:

因為光柵化處理后,圖元只是在屏幕上有了像素,卻沒有進行顏色處理,還是看不到東西。

因此FragmentsShader主要的作用是告訴GPU如何處理光照、陰影、遮擋、環境等,然后將結果輸出到gl_FragColor變量中

FragmentsShader只輸出一個顏色值——gl_FragColor,是片元著色器內置的輸出變量

片元著色器腳本示例:

#version 300 es

precision mediump float; // 設置精度限定符

in vec4 v_color;

out vec4 fragColor;

void main()

{

fragColor = v_color;

gl_FragColor = fragColor;

}

光柵化階段生成的顏色、深度、模板和屏幕坐標位置(Xw, Yw)將會變成逐片元操作階段的輸入值

Pre-Fragment Operations:逐片元操作階段

在片元著色器對片元進行綜合的處理,并最終為片元生成一個顏色值,并儲存在gl_FragColor變量后,接下來就是逐個對片元進行一些列的測試。

光柵化處理時,它由于時把頂點從世界坐標系轉換到屏幕坐標系,因此在光柵處理后,每個片元在屏幕上都有個坐標(Xw, Yw)。且存儲在了幀緩沖區(FrameBuffer),

包括片元著色器也是對(Xw, Yw)這個坐標的片元進行處理

Pixel ownership test——像素歸屬測試,它決定FrameBuffer中某個(Xw, Yw)位置的像素是否屬于當前Context

Scissor test——裁剪測試,決定一個位置(Xw, Yw)的片元是否位于裁剪舉行內,如果不在,則被丟棄

Stencil test/Depth test——模版和深度測試,傳入片元的模板和深度值,決定是否丟棄片

Blending——混合,將FragmentShader 新產生的片元顏色值和FrameBuffer中某個位置(Xw, Yw)的片元存儲的顏色值進行混合

Dithering——抖動,對可用顏色較少的系統,可以犧牲分辨率為代價,通過顏色值的抖動來增加可用顏色值。抖動操作和硬件相關,OpenGL允許程序員所有的操作就只有打開或關閉都懂操作。默認情況下抖動是激活的

在逐片元操作階段的最后,片元要么被舍棄,要么將顏色、深度、模板值寫入到幀緩沖區(Xw, Yw)位置,寫入的值取決于啟用的寫入掩碼

寫入掩碼可以更精細地控制寫入的顏色、深度、模板值。

備注:Alpha測試和邏輯操作不再是逐片元操作的一部分,這兩個階段存在于OpenGL2.0盒OpenGL1.x中。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,156評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,401評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,069評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,873評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,635評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,128評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,203評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,365評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,881評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,733評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,935評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,475評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,172評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,582評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,821評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,595評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,908評論 2 372

推薦閱讀更多精彩內容