著色器只能用在OpenGLES 2.X以上等可編程管道里吩愧,而在OpenGLES 1.X是不能使用的。
管線增显,Pipeline雁佳,顯卡執(zhí)行的、從幾何體到最終渲染圖像的同云、數(shù)據(jù)傳輸處理計(jì)算的過程
OpenGLES1.X中它是固定管道糖权,整體式封閉的,中間的各道工藝按固定的流程順序走炸站。如圖所示:
從上圖可以看出温兼,這些工藝順序是固定的,整個(gè)過程又分為:處理頂點(diǎn)武契,處理片元,驗(yàn)證片元信息并存入內(nèi)存
Rasterizer:光柵化處理,當(dāng)頂點(diǎn)處理完咒唆,會交給rasterizer來進(jìn)行光柵化處理届垫,結(jié)果會吧頂點(diǎn)的坐標(biāo)信息轉(zhuǎn)換成能在屏幕顯示的像素信息,即片元(Fragments)
生成片元后全释,接下來就是對fragments片元的各種驗(yàn)證装处,即過濾掉無用的片元,裁剪掉不在視野內(nèi)的片元浸船,最終把有效片元存儲入內(nèi)存中妄迁。
光柵化處理過程,就是把矢量圖轉(zhuǎn)化成像素點(diǎn)的過程李命。我們屏幕上顯示的畫面都是由像素組成登淘,而三維物體都是點(diǎn)線面構(gòu)成的。要讓點(diǎn)線面變成能在屏幕上顯示的像素封字,就需要Rasterizer這個(gè)過程黔州。
OpenGLES2.X可編程管道,由兩VertexShader(頂點(diǎn)著色器)阔籽、FragmentsShader(片元著色器)組成流妻,分別對應(yīng)上圖中的Coordinates 和Texture等藍(lán)色塊
OpenGLES2.0可渲染管道圖:
VertexShader:頂點(diǎn)著色器
頂點(diǎn)著色器輸入包括:
著色器程序——描述頂點(diǎn)上執(zhí)行操作的頂點(diǎn)著色器程序源代碼或者可執(zhí)行文件
頂點(diǎn)著色器輸入(或?qū)傩?——用頂點(diǎn)數(shù)組提供的每個(gè)頂點(diǎn)的數(shù)據(jù)
統(tǒng)一變量(uniform)——頂點(diǎn)(或片段)著色器使用的不變數(shù)據(jù)
采樣器——代表頂點(diǎn)著色器使用紋理的 特殊統(tǒng)一變量類型
頂點(diǎn)著色器的輸出在OpenGLES2.0稱作可變變量(varying),但在OpenGLES3.0中改名為頂點(diǎn)著色器輸出變量笆制。
在光柵化階段绅这,為每個(gè)生成的片段計(jì)算頂點(diǎn)著色器輸出值,并作為輸入傳遞給片段著色器在辆。
插值:光柵器對從頂點(diǎn)著色器傳遞的變量進(jìn)行插值
為了在屏幕上真正顯示证薇,必須將頂點(diǎn)著色器vs的輸出變量設(shè)置為gl_Position,gl_Position是一個(gè)保存著頂點(diǎn)齊次坐標(biāo)的4維向量开缎。ZYZ分量被W分量分割(稱作視角分割)并且XYZ分量上超過單位化盒子([-1, 1])的部分會被裁剪掉棕叫。最終的結(jié)果會被轉(zhuǎn)換到屏幕坐標(biāo)系然后三角形(或其它圖元類型)被光柵器生成對應(yīng)的像素。
OpenGLES3.0新增了一個(gè)功能——變換反饋奕删,使頂點(diǎn)著色器輸出可以選擇性地寫入一個(gè)輸出緩沖區(qū)(除了傳遞給片段著色器之外俺泣,也可用這種傳遞替代)
頂點(diǎn)著色器的輸入和輸出如下圖所示:
先看看腳本:
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”;
其中腳本語句關(guān)鍵字:
attribute:使用頂點(diǎn)數(shù)組封裝每個(gè)頂點(diǎn)的數(shù)據(jù),一般用于每個(gè)頂點(diǎn)都各不相同的變量完残,如頂點(diǎn)位置伏钠、顏色等
uniform:頂點(diǎn)著色器使用的常量數(shù)據(jù),不能被著色器修改谨设,一般用于對同一組頂點(diǎn)組成的單個(gè)3D物體中所有頂點(diǎn)都有相同的變量熟掂,如當(dāng)前光源位置
sampler:這是可選的,一種特殊的uniform扎拣,表示頂點(diǎn)著色器使用的紋理
mat4:表示4x4浮點(diǎn)數(shù)矩陣赴肚,該變量存儲了組合模型視圖和投影矩陣
vec4:表示包含了4個(gè)浮點(diǎn)數(shù)的向量
varying:用于從頂點(diǎn)著色器傳遞到片元或FragmentsShader傳遞到下一步的輸出變量
uMVPMatrix * aPosition:通過4x4 的變換位置后素跺,輸出給gl_Position,gl_Position是頂點(diǎn)著色器內(nèi)置的輸出變量誉券。
gl_FragColor:片元著色器內(nèi)置的輸出變量
PrimitiveAssembly:圖元裝配
圖元即圖形指厌,在OpenGL有幾個(gè)基本圖元:點(diǎn)、線踊跟、三角形踩验,其他的復(fù)雜圖元都是基于這些基本圖元來繪制而成。
在圖元裝配階段商玫,那些經(jīng)過頂點(diǎn)著色器(VertexShader)處理過的頂點(diǎn)數(shù)組或緩沖區(qū)的數(shù)據(jù)(VertexArrays/BufferObjects)箕憾,被組裝到一個(gè)個(gè)獨(dú)立的幾何圖形中(點(diǎn),線拳昌,三角形)
對裝配好的沒個(gè)圖元袭异,都必須確保它在世界坐標(biāo)系中,而對于不在世界坐標(biāo)系中的圖元地回,就必須進(jìn)行裁剪扁远,使其處于在世界坐標(biāo)系中才能流到下一道工序(光柵化處理)
這里還有一個(gè)剔除操作(Cull),前提是這個(gè)功能的開關(guān)是打開的:GLES20.glEnable(GLES20.GL_CULL_FACE); 剔除的是圖元的背影刻像,陰影畅买,背面等。
Rasterization:光柵化
光柵化階段繪制對應(yīng)的圖元(點(diǎn)细睡、線谷羞、三角形),將圖元轉(zhuǎn)化為一組二維數(shù)組的過程溜徙,然后傳遞給片段著色器處理湃缎。這些二維數(shù)組代表屏幕上繪制的像素
(PS:上圖中的點(diǎn)精靈光柵化應(yīng)該是點(diǎn)光柵化)
FragmentShader:片元著色器
片元著色器主要是對光柵化處理后生成的片元逐個(gè)進(jìn)行處理。接收頂點(diǎn)著色器輸出的值蠢壹,需要傳入的數(shù)據(jù)嗓违,以及它經(jīng)過變換矩陣后輸出值存儲位置。
著色器程序——描述片元所執(zhí)行的片元著色器程序源代碼
輸入變量——光柵器對頂點(diǎn)著色器插值后的輸出值
統(tǒng)一變量——片元(或頂點(diǎn))著色器使用的不變的數(shù)據(jù)
采樣器——代表片元著色器所用紋理的一種特殊的統(tǒng)一變量類型
片元著色器輸入和輸出關(guān)系如下圖所示:
因?yàn)楣鈻呕幚砗笸济常瑘D元只是在屏幕上有了像素蹂季,卻沒有進(jìn)行顏色處理,還是看不到東西疏日。
因此FragmentsShader主要的作用是告訴GPU如何處理光照偿洁、陰影、遮擋沟优、環(huán)境等涕滋,然后將結(jié)果輸出到gl_FragColor變量中
FragmentsShader只輸出一個(gè)顏色值——gl_FragColor,是片元著色器內(nèi)置的輸出變量
片元著色器腳本示例:
#version 300 es
precision mediump float; // 設(shè)置精度限定符
in vec4 v_color;
out vec4 fragColor;
void main()
{
fragColor = v_color;
gl_FragColor = fragColor;
}
光柵化階段生成的顏色挠阁、深度宾肺、模板和屏幕坐標(biāo)位置(Xw, Yw)將會變成逐片元操作階段的輸入值
Pre-Fragment Operations:逐片元操作階段
在片元著色器對片元進(jìn)行綜合的處理溯饵,并最終為片元生成一個(gè)顏色值,并儲存在gl_FragColor變量后爱榕,接下來就是逐個(gè)對片元進(jìn)行一些列的測試瓣喊。
光柵化處理時(shí),它由于時(shí)把頂點(diǎn)從世界坐標(biāo)系轉(zhuǎn)換到屏幕坐標(biāo)系黔酥,因此在光柵處理后,每個(gè)片元在屏幕上都有個(gè)坐標(biāo)(Xw, Yw)洪橘。且存儲在了幀緩沖區(qū)(FrameBuffer)跪者,
包括片元著色器也是對(Xw, Yw)這個(gè)坐標(biāo)的片元進(jìn)行處理
Pixel ownership test——像素歸屬測試,它決定FrameBuffer中某個(gè)(Xw, Yw)位置的像素是否屬于當(dāng)前Context
Scissor test——裁剪測試熄求,決定一個(gè)位置(Xw, Yw)的片元是否位于裁剪舉行內(nèi)渣玲,如果不在,則被丟棄
Stencil test/Depth test——模版和深度測試弟晚,傳入片元的模板和深度值忘衍,決定是否丟棄片
Blending——混合,將FragmentShader 新產(chǎn)生的片元顏色值和FrameBuffer中某個(gè)位置(Xw, Yw)的片元存儲的顏色值進(jìn)行混合
Dithering——抖動卿城,對可用顏色較少的系統(tǒng)枚钓,可以犧牲分辨率為代價(jià),通過顏色值的抖動來增加可用顏色值瑟押。抖動操作和硬件相關(guān)搀捷,OpenGL允許程序員所有的操作就只有打開或關(guān)閉都懂操作。默認(rèn)情況下抖動是激活的
在逐片元操作階段的最后多望,片元要么被舍棄嫩舟,要么將顏色、深度怀偷、模板值寫入到幀緩沖區(qū)(Xw, Yw)位置家厌,寫入的值取決于啟用的寫入掩碼
寫入掩碼可以更精細(xì)地控制寫入的顏色、深度椎工、模板值饭于。
備注:Alpha測試和邏輯操作不再是逐片元操作的一部分,這兩個(gè)階段存在于OpenGL2.0盒OpenGL1.x中晋渺。