基礎(chǔ)概念OpenGLES(一)

opengl es是什么?

  • opengl 是一個(gè)跨平臺(tái)(不同的GPU類型,如電腦端NVIDIA,Intel,AMD的顯卡,手機(jī)端PowerVR(蘋果系列), Adreno(高通,安卓系列)等等)、跨編程語(yǔ)言(各個(gè)編程語(yǔ)言java,C,OC,js等等都有opengl的接口)的圖形圖像處理接口,opengl本身只是一組api接口規(guī)范,具體的實(shí)現(xiàn)一般是由具體的顯卡(GPU)設(shè)備生產(chǎn)商編碼實(shí)現(xiàn)的,比如蘋果手機(jī)是由apple實(shí)現(xiàn)的,Linux系統(tǒng)則是由各個(gè)顯卡生產(chǎn)商通過(guò)驅(qū)動(dòng)程序?qū)氲摹?/p>

  • opengl es是opengl的一個(gè)子集,是專門用來(lái)針對(duì)手機(jī),平板電腦等嵌入式設(shè)備的圖形圖像處理接口,接口設(shè)計(jì)中不涉及上下文環(huán)境和窗口的管理,這由各個(gè)平臺(tái)自行實(shí)現(xiàn)。比如ios就是EAGL;安卓就是EGL;

tips:
libSDL是一個(gè)跨平臺(tái)的圖形處理庫(kù),其中有包含對(duì)opengl es的標(biāo)準(zhǔn)接口的封裝及各個(gè)平臺(tái)上下文,窗口管理的封裝。
備注:opengl es 2.0 官方接口文檔 https://www.khronos.org/registry/OpenGL-Refpages/es2.0/

基礎(chǔ)概念

  • 應(yīng)用端:
    即我們自己的程序端,相對(duì)于opengl es,我們屬于應(yīng)用端
  • 圖元:
    要渲染的幾何物體,或者形狀。比如要渲染一個(gè)正方形的圖片,就是一個(gè)圖元,要渲染兩條直線,這兩條直線也是圖元
  • 紋理:
    通俗點(diǎn),可以理解為一張圖片,在opengl es中紋理就是圖片的另外一種叫法
  • 紋素:
    紋理的基礎(chǔ)單元,也就是像素
  • 頂點(diǎn)數(shù)組
    頂點(diǎn)指的是組成圖元的各個(gè)頂點(diǎn)的坐標(biāo)數(shù)據(jù)(在3D笛卡爾坐標(biāo)中即x,y,z坐標(biāo)),這些坐標(biāo)數(shù)據(jù)可以一起存到一個(gè)內(nèi)存數(shù)組中,這個(gè)數(shù)組就叫做頂點(diǎn)數(shù)組
  • 頂點(diǎn)緩沖區(qū)
    在顯存中專門分配一塊顯存來(lái)存儲(chǔ)這個(gè)頂點(diǎn)數(shù)組,這個(gè)顯存就稱為頂點(diǎn)緩沖區(qū)
  • 頂點(diǎn)著色器
    頂點(diǎn)著??(簡(jiǎn)稱為VS)是opengl es中?于計(jì)算圖形頂點(diǎn)屬性(包括頂點(diǎn)坐標(biāo)歸一化、頂點(diǎn)光照運(yùn)算等等)的程序。頂點(diǎn)著色?是逐頂點(diǎn)運(yùn)算的程序,也就是說(shuō)每個(gè)頂點(diǎn)數(shù)據(jù)都會(huì)執(zhí)行?次頂點(diǎn)著??,當(dāng)然這是并行的
  • 片元著色器
    片元著色器(簡(jiǎn)稱為PS)用來(lái)決定要渲染圖形的每個(gè)像素的顏色的程序,它也是并行計(jì)算的

opengl es渲染管線

渲染管線也就是opengl es的工作流程,這里是opengl es2.0以后的版本的渲染管線

  • 1、opengl es接收API的輸入
    通過(guò) API 設(shè)定頂點(diǎn)的信息(一般包括頂點(diǎn)坐標(biāo),紋理坐標(biāo),顏色,變換矩陣等等),一般由頂點(diǎn)著色器接收這些信息作為輸入
  • 2、頂點(diǎn)著色器處理頂點(diǎn)坐標(biāo)
    前一階段的輸入將在 VS 中進(jìn)行運(yùn)算,以得到最終的頂點(diǎn)坐標(biāo)。
  • 3、圖元裝配
    將頂點(diǎn)著色器計(jì)算出的最終頂點(diǎn)坐標(biāo)進(jìn)行圖元裝配,構(gòu)建出最終想要渲染的圖形。所有要渲染的圖形都可以由三個(gè)基本的圖元(點(diǎn)、線、三角形)組成,比如正方形或者長(zhǎng)方形,就可以由兩個(gè)三角形組成,圓形可以由無(wú)數(shù)個(gè)三角形組成,只是三角形的數(shù)量越多,圓形看上去越圓潤(rùn)
  • 4、光柵化
    通過(guò)計(jì)算,將要渲染的圖形上所有的像素點(diǎn)找到,并根據(jù)插值或者其他方式計(jì)算出其顏色等信息的過(guò)程
  • 5、片元著色器計(jì)算像素顏色
    光柵化得到了要渲染圖形的所有像素的信息,這些信息作為片元著色器的輸入,那么在片元著色器中將計(jì)算像素顏色
  • 6、像素處理
    片元著色器計(jì)算的像素顏色還不是最終要渲染的顏色,這一步驟還包括Alpha Test、Depth/Stencil Test、Blend、Dither等幾個(gè)步驟,經(jīng)過(guò)這幾個(gè)步驟后得到的就是最終的渲染顏色

備注:以上所有的操作都是并行處理

opengl es的相關(guān)坐標(biāo)系

  • opengl es的坐標(biāo)系原點(diǎn)位于要渲染區(qū)域的中心點(diǎn),向右和向上分別為x軸和y軸的正向軸,取值范圍為(-1,1)
    如下為正確渲染一張圖片為例傳遞頂點(diǎn)坐標(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ū)域;實(shí)際上就是壓縮效果
    static float verData1[8] = {
    -2.0f, -2.0f, // 左下角
    2.0f,-2.0f, // 右下角
    -2.0f,2.0f, // 左上角
    2.0f,2.0f, // 右上角
    };
    表示將原來(lái)的坐標(biāo)系放大了一倍后在基于原始的進(jìn)行截取

  • 紋理坐標(biāo)系
    在opengl 中,通常將紋理中的像素根據(jù)紋理坐標(biāo)系來(lái)進(jìn)行編址,紋理坐標(biāo)系的橫軸成為S軸,縱軸成為T軸,垂直于ST軸的成為R軸,在2D紋理中,沒(méi)有
    R軸,橫軸和縱軸又稱為UV軸,所以2D紋理坐標(biāo)系又稱為UV坐標(biāo)系,UV軸的取值范圍都是(0,1)。與OpenGL 坐標(biāo)系不同的是,紋理坐標(biāo)系的原點(diǎn)位于左
    上角
    如下為正確渲染一張圖片為例傳遞紋理坐標(biāo):
    static float uvData[8] = {
    0.0f, 1.0f,// 左下角
    1.0f, 1.0f, // 右下角
    0.0f, 0.0f,// 左上角
    1.0f, 0.0f, // 右上角
    };
    紋理坐標(biāo)系一般不要去改變它的值,傳這個(gè)就好,(當(dāng)然也可該,前提是知道內(nèi)部的轉(zhuǎn)換原理),如果要實(shí)現(xiàn)壓縮和裁剪效果,改變幾何坐標(biāo)系方便一些。

  • 設(shè)定opengl es渲染區(qū)域
    glViewPort(x,y,w,h) 函數(shù)窗口創(chuàng)建的渲染區(qū)域
    它以左下角作為原點(diǎn)的坐標(biāo)系
    此函數(shù)的意思就是,基于當(dāng)前視圖左下角作為原點(diǎn)的坐標(biāo)系,選取一個(gè)左下角坐標(biāo)為x,y,長(zhǎng)寬為w,h的區(qū)域作為渲染的區(qū)域

紋理映射

  • 1、縮放
    紋理的映射就是讓物體的每個(gè)片元(每個(gè)顏色像素)都找到對(duì)應(yīng)的紋理紋素點(diǎn),在這個(gè)映射過(guò)程中,因?yàn)榧y理和物體的不匹配,一般會(huì)出現(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:
    是多個(gè)紋素對(duì)應(yīng)一個(gè)片元的解決方案??梢栽O(shè)置兩個(gè)值,GL_NEAREST 和 GL_LINEAR ,這兩個(gè)值分別對(duì)應(yīng)了兩種不同的解決方案。GL_LINEAR 會(huì)混合匹配的顏色來(lái)得到片元的顏色,產(chǎn)生的顏色可能是紋理中不存在的顏色。例如一個(gè)紋理是由交替的黑色和白色的紋素組成,那個(gè)線性取樣會(huì)使最終的片元顏色為灰色。GL_NEAREST 會(huì)拾取與片元 U,V 坐標(biāo)最相近的顏色。
    GL_TEXTURE_MAG_FILTER:
    是沒(méi)有足夠的紋素來(lái)映射片元的解決方案。可以設(shè)置的值同 GL_TEXTURE_MIN_FILTER 一樣。GL_LINEAR 會(huì)告訴OpenGL ES 混合附近紋素的顏色來(lái)計(jì)算片元的顏色。GL_LINEAR會(huì)有一個(gè)放大紋理的效果,當(dāng)沒(méi)有足夠的紋素來(lái)映射片元時(shí),會(huì)讓紋理模糊的出現(xiàn)在要渲染的圖形上。
    GL_NEAREST 僅僅會(huì)拾取片元的 U ,V 位置接近的紋素的顏色,并放大紋理,會(huì)使其像素化的出現(xiàn)在要渲染的圖形上。
    GL_LINEAR:
    線性插值,取最近的點(diǎn)的線性平均值 (性能消耗較大)
    mipmaps
    它也是一種紋理過(guò)濾算法,按我的理解它是以空間換時(shí)間的一種技巧,具體原理就是事先根據(jù)紋理生成長(zhǎng)和寬逐漸除以2的小紋理,比如原始紋理大小128x128,
    采用此方法后,會(huì)生成64x64 32x32 16x16 8x8 4x4 2x2 1x1的一系列紋理,如果需要20x18的紋理,則取最近的32x32 16x16進(jìn)行平均
    該方法很好的解決了如下問(wèn)題:
    1、當(dāng)紋理很大,但是屏幕區(qū)域很小,渲染出現(xiàn)的閃爍問(wèn)題,因?yàn)楦鶕?jù)最鄰近插值和線性插值都無(wú)法很快計(jì)算出合理的像素
    它可以取的值如下:
    GL_NEAREST_MIPMAP_NEAREST 選擇最近的mipmap層,然后再用最鄰近過(guò)濾插值
    GL_LINEAR_MIPMAP_NEAREST 選擇最近mipmap層,然后再用線性插值
    GL_NEAREST_MIPMAP_LINEAR 選擇最近的2層mipmap用最鄰近過(guò)濾插值
    GL_LINEAR_MIPMAP_LINEAR 選擇最鄰近的2層mipmap用線性插值
    使用如下函數(shù)生成mipmaps
    glGenerateMipmap(GLenum target);

  • 2、warp
    另外一種在映射時(shí)可能出現(xiàn)的情況是紋理的四個(gè)頂點(diǎn)坐標(biāo)不是1.0時(shí),將采用如下方式:
    glTexParameter(GL_TEXTURE_2D,GL_TEXTURE_WARP_S,GL_REPEAT) S軸方向
    glTexParameter(GL_TEXTURE_2D,GL_TEXTURE_WARP_T,GL_REPEAT) T軸方向
    GL_REPEAT:紋理沒(méi)有覆蓋的部分重復(fù)之前的紋理,當(dāng)紋理大小大于物體大小時(shí),紋理采樣會(huì)出錯(cuò)。
    GL_MIRRODED_REPEAT:將原來(lái)的紋理先顛倒再重復(fù),當(dāng)紋理大小大于物體大小時(shí),紋理采樣會(huì)出錯(cuò)。
    GL_CLAMP_TO_EDGE:延續(xù)結(jié)束時(shí)的紋理

頂點(diǎn)著色器中頂點(diǎn)坐標(biāo)的順序規(guī)則

open gl 中頂點(diǎn)坐標(biāo)
static float verData1[8] = {
-1.0f,-1.0f, // 左下角
1.0f,-1.0f, // 右下角
-1.0f,1.0f, // 左上角
1.0f,1.0f, // 右上角
};
對(duì)應(yīng)的紋理坐標(biāo)
static float uvData[8] = {
0.0f, 1.0f, // 左下角
1.0f, 1.0f, // 右下角
0.0f, 0.0f, // 左上角
1.0f, 0.0f, // 右上角
};
對(duì)應(yīng)的為glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 可以渲染出一張圖片

VBO

GPU中專門開辟的一塊內(nèi)存用于存儲(chǔ)圖元的頂點(diǎn)數(shù)據(jù),這樣每次調(diào)用glDrawArrays()函數(shù)時(shí),GLSL就是直接從GPU中獲取
頂點(diǎn)數(shù)據(jù),而不是每次都有cpu拷貝到GPU(cpu拷貝到gpu肯定效率不如直接從GPU中取),這樣對(duì)于頂點(diǎn)數(shù)據(jù)比較多時(shí),
可以加快效率;

FBO

幀緩沖,也就是通過(guò)glGenFramebuffers()函數(shù)生成的對(duì)象,它主要用于存儲(chǔ)opengl es最終的渲染結(jié)果。

離屏渲染

當(dāng)需要對(duì)紋理進(jìn)行多次渲染采樣時(shí)(也就是對(duì)一個(gè)紋理進(jìn)行多個(gè)著色器程序去處理),而這些渲染采樣中間過(guò)程是不需要
展示給用戶看的,所以就可以額外創(chuàng)建一個(gè)FBO對(duì)象來(lái)專門做這個(gè)事情,這個(gè)FPO對(duì)象就成為為離屏渲染幀緩沖,這個(gè)
過(guò)程叫做離屏渲染

渲染緩沖區(qū)

通過(guò)glGenRenderbuffers()生成的緩沖區(qū),他用于將渲染的結(jié)果呈現(xiàn)到屏幕上,需要與FBO綁定

opengl es api和EGL api

opengl es api是用來(lái)進(jìn)行圖像渲染操作的,
egl api是由各個(gè)操作系統(tǒng)實(shí)現(xiàn)的系統(tǒng)api,它主要的作用就是創(chuàng)建窗口,創(chuàng)建opengl 上下文環(huán)境等??梢杂筛髯詮S商自行定義,使用通用的EGL接口。
如蘋果就是EAGL,安卓就可以用EGL來(lái)自行管理,也可以用GLSurface系統(tǒng)創(chuàng)建opengl 環(huán)境

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容