opengl es是什么钾唬?
opengl 是一個跨平臺(不同的GPU類型惫东,如電腦端NVIDIA,Intel,AMD的顯卡,手機(jī)端PowerVR(蘋果系列), Adreno(高通,安卓系列)等等)辫封、跨編程語言(各個編程語言java,C,OC,js等等都有opengl的接口)的圖形圖像處理接口侠碧,opengl本身只是一組api接口規(guī)范抹估,具體的實現(xiàn)一般是由具體的顯卡(GPU)設(shè)備生產(chǎn)商編碼實現(xiàn)的,比如蘋果手機(jī)是由apple實現(xiàn)的弄兜,Linux系統(tǒng)則是由各個顯卡生產(chǎn)商通過驅(qū)動程序?qū)氲摹?/p>
opengl es是opengl的一個子集药蜻,是專門用來針對手機(jī),平板電腦等嵌入式設(shè)備的圖形圖像處理接口替饿,接口設(shè)計中不涉及上下文環(huán)境和窗口的管理语泽,這由各個平臺自行實現(xiàn)。比如ios就是EAGL视卢;安卓就是EGL踱卵;
tips:
libSDL是一個跨平臺的圖形處理庫,其中有包含對opengl es的標(biāo)準(zhǔn)接口的封裝及各個平臺上下文据过,窗口管理的封裝惋砂。
備注:opengl es 2.0 官方接口文檔 https://www.khronos.org/registry/OpenGL-Refpages/es2.0/
基礎(chǔ)概念
- 應(yīng)用端:
即我們自己的程序端,相對于opengl es绳锅,我們屬于應(yīng)用端 - 圖元:
要渲染的幾何物體班利,或者形狀。比如要渲染一個正方形的圖片榨呆,就是一個圖元罗标,要渲染兩條直線,這兩條直線也是圖元 - 紋理:
通俗點积蜻,可以理解為一張圖片闯割,在opengl es中紋理就是圖片的另外一種叫法 - 紋素:
紋理的基礎(chǔ)單元,也就是像素 - 頂點數(shù)組
頂點指的是組成圖元的各個頂點的坐標(biāo)數(shù)據(jù)(在3D笛卡爾坐標(biāo)中即x,y,z坐標(biāo))竿拆,這些坐標(biāo)數(shù)據(jù)可以一起存到一個內(nèi)存數(shù)組中宙拉,這個數(shù)組就叫做頂點數(shù)組 - 頂點緩沖區(qū)
在顯存中專門分配一塊顯存來存儲這個頂點數(shù)組,這個顯存就稱為頂點緩沖區(qū) - 頂點著色器
頂點著??(簡稱為VS)是opengl es中?于計算圖形頂點屬性(包括頂點坐標(biāo)歸一化丙笋、頂點光照運算等等)的程序谢澈。頂點著色?是逐頂點運算的程序,也就是說每個頂點數(shù)據(jù)都會執(zhí)行?次頂點著??御板,當(dāng)然這是并行的 - 片元著色器
片元著色器(簡稱為PS)用來決定要渲染圖形的每個像素的顏色的程序锥忿,它也是并行計算的
opengl es渲染管線
渲染管線也就是opengl es的工作流程,這里是opengl es2.0以后的版本的渲染管線
- 1怠肋、opengl es接收API的輸入
通過 API 設(shè)定頂點的信息(一般包括頂點坐標(biāo)敬鬓,紋理坐標(biāo),顏色,變換矩陣等等)钉答,一般由頂點著色器接收這些信息作為輸入 - 2础芍、頂點著色器處理頂點坐標(biāo)
前一階段的輸入將在 VS 中進(jìn)行運算,以得到最終的頂點坐標(biāo)。 - 3数尿、圖元裝配
將頂點著色器計算出的最終頂點坐標(biāo)進(jìn)行圖元裝配,構(gòu)建出最終想要渲染的圖形仑性。所有要渲染的圖形都可以由三個基本的圖元(點、線右蹦、三角形)組成诊杆,比如正方形或者長方形,就可以由兩個三角形組成,圓形可以由無數(shù)個三角形組成,只是三角形的數(shù)量越多,圓形看上去越圓潤 - 4、光柵化
通過計算嫩实,將要渲染的圖形上所有的像素點找到,并根據(jù)插值或者其他方式計算出其顏色等信息的過程 - 5刽辙、片元著色器計算像素顏色
光柵化得到了要渲染圖形的所有像素的信息,這些信息作為片元著色器的輸入甲献,那么在片元著色器中將計算像素顏色 - 6宰缤、像素處理
片元著色器計算的像素顏色還不是最終要渲染的顏色,這一步驟還包括Alpha Test晃洒、Depth/Stencil Test慨灭、Blend、Dither等幾個步驟球及,經(jīng)過這幾個步驟后得到的就是最終的渲染顏色
備注:以上所有的操作都是并行處理
opengl es的相關(guān)坐標(biāo)系
opengl es的坐標(biāo)系原點位于要渲染區(qū)域的中心點氧骤,向右和向上分別為x軸和y軸的正向軸,取值范圍為(-1,1)
如下為正確渲染一張圖片為例傳遞頂點坐標(biāo)
static float verData1[8] = {
-1.0f, -1.0f, // 左下角
1.0f,-1.0f, // 右下角
-1.0f,1.0f, // 左上角
1.0f,1.0f, // 右上角
};
一般按照如上的順序傳遞坐標(biāo)吃引,取值也可以是其它值筹陵,比如
static float verData1[8] = {
-0.5f, -0.5f, // 左下角
0.5f,-0.5f, // 右下角
-0.5f,0.5f, // 左上角
0.5f,0.5f, // 右上角
};
表示取中間的1/2區(qū)域;實際上就是壓縮效果
static float verData1[8] = {
-2.0f, -2.0f, // 左下角
2.0f,-2.0f, // 右下角
-2.0f,2.0f, // 左上角
2.0f,2.0f, // 右上角
};
表示將原來的坐標(biāo)系放大了一倍后在基于原始的進(jìn)行截取紋理坐標(biāo)系
在opengl 中镊尺,通常將紋理中的像素根據(jù)紋理坐標(biāo)系來進(jìn)行編址朦佩,紋理坐標(biāo)系的橫軸成為S軸,縱軸成為T軸庐氮,垂直于ST軸的成為R軸语稠,在2D紋理中,沒有
R軸弄砍,橫軸和縱軸又稱為UV軸仙畦,所以2D紋理坐標(biāo)系又稱為UV坐標(biāo)系,UV軸的取值范圍都是(0,1)音婶。與OpenGL 坐標(biāo)系不同的是慨畸,紋理坐標(biāo)系的原點位于左
上角
如下為正確渲染一張圖片為例傳遞紋理坐標(biāo):
static float uvData[8] = {
0.0f, 1.0f,// 左下角
1.0f, 1.0f, // 右下角
0.0f, 0.0f,// 左上角
1.0f, 0.0f, // 右上角
};
紋理坐標(biāo)系一般不要去改變它的值,傳這個就好桃熄,(當(dāng)然也可該先口,前提是知道內(nèi)部的轉(zhuǎn)換原理),如果要實現(xiàn)壓縮和裁剪效果型奥,改變幾何坐標(biāo)系方便一些瞳收。設(shè)定opengl es渲染區(qū)域
glViewPort(x,y,w,h) 函數(shù)窗口創(chuàng)建的渲染區(qū)域
它以左下角作為原點的坐標(biāo)系
此函數(shù)的意思就是碉京,基于當(dāng)前視圖左下角作為原點的坐標(biāo)系,選取一個左下角坐標(biāo)為x,y,長寬為w,h的區(qū)域作為渲染的區(qū)域
紋理映射
1螟深、縮放
紋理的映射就是讓物體的每個片元(每個顏色像素)都找到對應(yīng)的紋理紋素點谐宙,在這個映射過程中,因為紋理和物體的不匹配界弧,一般會出現(xiàn)兩種情況
第一種是擁有大量紋素的紋理被映射到只還有少量片元的物體中
第二種是擁有少量紋素的紋理被映射到含有大量片元的物體中
如下:
glTexParameter(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR)
glTexParameter(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR)
GL_TEXTURE_MIN_FILTER:
是多個紋素對應(yīng)一個片元的解決方案凡蜻。可以設(shè)置兩個值,GL_NEAREST 和 GL_LINEAR 垢箕,這兩個值分別對應(yīng)了兩種不同的解決方案划栓。GL_LINEAR 會混合匹配的顏色來得到片元的顏色,產(chǎn)生的顏色可能是紋理中不存在的顏色条获。例如一個紋理是由交替的黑色和白色的紋素組成忠荞,那個線性取樣會使最終的片元顏色為灰色。GL_NEAREST 會拾取與片元 U帅掘,V 坐標(biāo)最相近的顏色委煤。
GL_TEXTURE_MAG_FILTER:
是沒有足夠的紋素來映射片元的解決方案⌒薜担可以設(shè)置的值同 GL_TEXTURE_MIN_FILTER 一樣碧绞。GL_LINEAR 會告訴OpenGL ES 混合附近紋素的顏色來計算片元的顏色。GL_LINEAR會有一個放大紋理的效果吱窝,當(dāng)沒有足夠的紋素來映射片元時讥邻,會讓紋理模糊的出現(xiàn)在要渲染的圖形上。
GL_NEAREST 僅僅會拾取片元的 U 院峡,V 位置接近的紋素的顏色兴使,并放大紋理,會使其像素化的出現(xiàn)在要渲染的圖形上撕予。
GL_LINEAR:
線性插值鲫惶,取最近的點的線性平均值 (性能消耗較大)
mipmaps
它也是一種紋理過濾算法,按我的理解它是以空間換時間的一種技巧实抡,具體原理就是事先根據(jù)紋理生成長和寬逐漸除以2的小紋理欠母,比如原始紋理大小128x128,
采用此方法后吆寨,會生成64x64 32x32 16x16 8x8 4x4 2x2 1x1的一系列紋理赏淌,如果需要20x18的紋理,則取最近的32x32 16x16進(jìn)行平均
該方法很好的解決了如下問題:
1啄清、當(dāng)紋理很大六水,但是屏幕區(qū)域很小,渲染出現(xiàn)的閃爍問題,因為根據(jù)最鄰近插值和線性插值都無法很快計算出合理的像素
它可以取的值如下:
GL_NEAREST_MIPMAP_NEAREST 選擇最近的mipmap層掷贾,然后再用最鄰近過濾插值
GL_LINEAR_MIPMAP_NEAREST 選擇最近mipmap層睛榄,然后再用線性插值
GL_NEAREST_MIPMAP_LINEAR 選擇最近的2層mipmap用最鄰近過濾插值
GL_LINEAR_MIPMAP_LINEAR 選擇最鄰近的2層mipmap用線性插值
使用如下函數(shù)生成mipmaps
glGenerateMipmap(GLenum target);2、warp
另外一種在映射時可能出現(xiàn)的情況是紋理的四個頂點坐標(biāo)不是1.0時想帅,將采用如下方式:
glTexParameter(GL_TEXTURE_2D,GL_TEXTURE_WARP_S,GL_REPEAT) S軸方向
glTexParameter(GL_TEXTURE_2D,GL_TEXTURE_WARP_T,GL_REPEAT) T軸方向
GL_REPEAT:紋理沒有覆蓋的部分重復(fù)之前的紋理场靴,當(dāng)紋理大小大于物體大小時,紋理采樣會出錯港准。
GL_MIRRODED_REPEAT:將原來的紋理先顛倒再重復(fù)旨剥,當(dāng)紋理大小大于物體大小時,紋理采樣會出錯浅缸。
GL_CLAMP_TO_EDGE:延續(xù)結(jié)束時的紋理
頂點著色器中頂點坐標(biāo)的順序規(guī)則
open gl 中頂點坐標(biāo)
static float verData1[8] = {
-1.0f,-1.0f, // 左下角
1.0f,-1.0f, // 右下角
-1.0f,1.0f, // 左上角
1.0f,1.0f, // 右上角
};
對應(yīng)的紋理坐標(biāo)
static float uvData[8] = {
0.0f, 1.0f, // 左下角
1.0f, 1.0f, // 右下角
0.0f, 0.0f, // 左上角
1.0f, 0.0f, // 右上角
};
對應(yīng)的為glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 可以渲染出一張圖片
VBO
GPU中專門開辟的一塊內(nèi)存用于存儲圖元的頂點數(shù)據(jù),這樣每次調(diào)用glDrawArrays()函數(shù)時轨帜,GLSL就是直接從GPU中獲取
頂點數(shù)據(jù),而不是每次都有cpu拷貝到GPU(cpu拷貝到gpu肯定效率不如直接從GPU中取)衩椒,這樣對于頂點數(shù)據(jù)比較多時蚌父,
可以加快效率;
FBO
幀緩沖烟具,也就是通過glGenFramebuffers()函數(shù)生成的對象梢什,它主要用于存儲opengl es最終的渲染結(jié)果。
離屏渲染
當(dāng)需要對紋理進(jìn)行多次渲染采樣時(也就是對一個紋理進(jìn)行多個著色器程序去處理)朝聋,而這些渲染采樣中間過程是不需要
展示給用戶看的嗡午,所以就可以額外創(chuàng)建一個FBO對象來專門做這個事情,這個FPO對象就成為為離屏渲染幀緩沖,這個
過程叫做離屏渲染
渲染緩沖區(qū)
通過glGenRenderbuffers()生成的緩沖區(qū)冀痕,他用于將渲染的結(jié)果呈現(xiàn)到屏幕上荔睹,需要與FBO綁定
opengl es api和EGL api
opengl es api是用來進(jìn)行圖像渲染操作的,
egl api是由各個操作系統(tǒng)實現(xiàn)的系統(tǒng)api言蛇,它主要的作用就是創(chuàng)建窗口僻他,創(chuàng)建opengl 上下文環(huán)境等±吧校可以由各自廠商自行定義吨拗,使用通用的EGL接口。
如蘋果就是EAGL婿斥,安卓就可以用EGL來自行管理劝篷,也可以用GLSurface系統(tǒng)創(chuàng)建opengl 環(huán)境