前言
從接觸到OpenGL之后發(fā)現(xiàn)它很神奇,為什么它能渲染出圖片埋涧,要搞懂其原理板辽,前提是要知道怎么用。本文不講其原理棘催,目前我的水平對底層GPU如何渲染還很難說的清楚劲弦,網(wǎng)上的帖子太多了,真正講明白的沒幾個(gè)醇坝,至今沒有發(fā)現(xiàn)邑跪,可能是原理過于偏低層,而國內(nèi)真正研究過原理又留下自己足跡可能都是在院泻糁恚或者研究所画畅,而這些文章普遍都是英文的,不禁感慨一下宋距,學(xué)好英文真的很重要轴踱,學(xué)會(huì)OpenGL不會(huì)過時(shí),畢竟會(huì)用OpenGL的人也不多(相對于中國程序員基數(shù))谚赎,用的精通的人更少了(可能會(huì)有噴我桶唐,但是OpenGL用處還是挺多的)憎妙∩春妫回到本文主題类嗤,學(xué)習(xí)OpenGL ES之前,還是要了解一下OpenGL ES的概念闸盔。本文的目的是OpenGL ES的概念掃盲悯辙。也是防止自己忘記。
對于剛?cè)腴T的同學(xué),建議可以先看下LearnOpenGL-CN
OpenGL ES
OpenGL是Open Graphics Library的縮寫笑撞。是跨平臺(tái),跨編程語言的編程接口的標(biāo)準(zhǔn)钓觉。用于調(diào)試硬件的2D茴肥、3D圖形處理器。由于是只軟件接口荡灾,所以具體底層實(shí)現(xiàn)依賴硬件設(shè)備制造商瓤狐。
OpenGL ES是OpenGL for Embedded Systems的縮寫。 是OpenGL的三維圖形API子集批幌。是針對手機(jī)础锐、PDA和游戲主機(jī)等嵌入式設(shè)備而設(shè)計(jì),去除了很多不必要和性能較低的API荧缘。
常用基本概念
頂點(diǎn)
物體的頂點(diǎn)皆警,對于一個(gè)2D圖片有四個(gè)頂點(diǎn)。對于一個(gè)3D正方體有8個(gè)頂點(diǎn)截粗。
圖元
繪制最小單元信姓,對于OpenGL ES來說可以是點(diǎn),線绸罗,三角形意推。
片元
圖片經(jīng)過計(jì)算后由若干個(gè)圖元組成的集合體。如下圖所示, 一個(gè)正方形是由兩個(gè)三角形組成
紋理
是一個(gè)2D圖片(甚至也有1D和3D的紋理)珊蟀,它可以用來添加物體的細(xì)節(jié)菊值。可以一個(gè)物體表面貼上不同的圖片育灸,如下圖所示:
著色器(shader)
著色器(Shader)是運(yùn)行在GPU上的小程序,可以處理頂點(diǎn)和片元相關(guān)計(jì)算腻窒。
著色器變量:
Attribute變量:是3D物體中每個(gè)頂點(diǎn)各自不同的信息所屬的變量,一般頂點(diǎn)的位置磅崭、顏色定页、法向量等每個(gè)頂點(diǎn)各自不同的信息都是以attribute變量的方式傳入頂點(diǎn)著色器內(nèi)。
Uniform變量:是對于同一組頂點(diǎn)組成的單個(gè)3D物體中所有頂點(diǎn)都相同的量绽诚,一般為場景中當(dāng)前的光源位置典徊、當(dāng)前的攝像機(jī)位置、投影系列矩陣等恩够。
Varying變量(易變變量):是從頂點(diǎn)著色器計(jì)算產(chǎn)生并傳遞到片元著色器的數(shù)據(jù)變量卒落。頂點(diǎn)著色器可以使用易變變量來傳遞需要插值到片元的顏色、法向量蜂桶、紋理坐標(biāo)等任意值儡毕。
gl_Position:是OpenGL內(nèi)置變量,用于存放坐標(biāo)變化后要渲染的頂點(diǎn)數(shù)據(jù)
gl_FragColor:是OpenGL內(nèi)置變量,是片元的最終顏色腰湾,在片元著色器的最后都需要對其進(jìn)行賦值雷恃。
頂點(diǎn)著色器
概述:頂點(diǎn)著色器提供頂點(diǎn)操作的編程程序。
輸入變量:Attribute變量和Uniforms變量费坊、Sampler采樣器.
輸出變量:內(nèi)建變量gl_Position等.
Attribute(屬性變量): 用頂點(diǎn)數(shù)組提供的逐頂點(diǎn)數(shù)據(jù).
Uniforms(統(tǒng)一變量) : 頂點(diǎn)著色器使用的不變數(shù)據(jù)倒槐,比如MVP矩陣.
Sampler(采樣器) : 代表頂點(diǎn)著色器使用的紋理的特殊統(tǒng)一變量類型.
VertexShader(頂點(diǎn)著色器程序) : 頂點(diǎn)著色器程序源代碼或者描述在操作頂點(diǎn)的可執(zhí)行文件.
片元著色器
概述:片元著色器提供片元著色操作的編程程序。
輸入變量:Varying變量和Uniforms變量附井、Sampler采樣器讨越。
輸出變量:內(nèi)建變量gl_FragColor等.
Varying(易變量): 由頂點(diǎn)著色器傳遞進(jìn)片元著色器沒有屬性attribute變量。光柵化單元用插值為每個(gè)片段生成的頂點(diǎn)著?器輸出(可以理解為這部分?jǐn)?shù)據(jù)是系統(tǒng)生成)
Uniforms(統(tǒng)一變量) : ?元著?器使用的不變數(shù)據(jù)永毅,比如旋轉(zhuǎn)矩陣
Sampler(采樣器) : 代表片元著?器使?紋理的特殊統(tǒng)一變量類型.獲取到紋理ID從內(nèi)存中查找對應(yīng)的紋理
FragShader(片元著色器程序) : 片元著色器程序源代碼或者描述在操作頂點(diǎn)的可執(zhí)行文件.
坐標(biāo)系統(tǒng)
3D物體渲染到本地視圖上所經(jīng)轉(zhuǎn)換的所有系統(tǒng)把跨。
OpenGL是可以繪制3D物體的,那3D物體如何從其表示3D物體的本地坐標(biāo)系一步步轉(zhuǎn)換到屏蔽坐標(biāo)系呢沼死?
從下圖可以看到着逐,一個(gè)3D從分別從本地空間轉(zhuǎn)換到世界空間,再到視圖空間意蛀,經(jīng)過裁剪空間滨嘱,最后到屏幕空間,才能顯示到我們手機(jī)上浸间。
MVP矩陣
此MVP非“MVP”; MVP是Model View Projection三者的縮寫太雨。我們從上圖可以看到從不同空間進(jìn)行轉(zhuǎn)換時(shí)需要經(jīng)過矩陣運(yùn)算,大學(xué)線性代數(shù)知識(shí)可知:從一個(gè)坐標(biāo)系轉(zhuǎn)換到另一個(gè)坐標(biāo)系時(shí)魁蒜,只需要乘相應(yīng)坐標(biāo)變換矩陣即可囊扳。這里MVP矩陣,其實(shí)是Model Matrix兜看、View Matrix锥咸、Projection Matrix三者相乘的結(jié)果。
根據(jù)線性代數(shù)基轉(zhuǎn)換原理:乘法順序一定要按照:Projection Matrix * View Matrix * Model Matrix细移。
對于矩陣的運(yùn)算搏予,在ndk編程中可以引用OpenGL Mathematics
模型矩陣
模型矩陣變換有三種變換:
- 平移變換:3D物體沿著某個(gè)方向進(jìn)行平移,物體大小不變弧轧;
glm接口:
Model = glm::translate(Model, glm::vec3(x, y, z));
- 旋轉(zhuǎn)變換:物體沿著某個(gè)對稱軸進(jìn)行旋轉(zhuǎn)雪侥,物體大小不變;
glm接口:
Model = glm::rotate(Model, glm::radians(pitch), glm::vec3(pitchSymbolFactor, 0.0f, 0.0f));
Model = glm::rotate(Model, glm::radians(yaw), glm::vec3(0.0f, yawSymbolFactor, 0.0f));
Model = glm::rotate(Model, glm::radians(roll), glm::vec3(0.0f, 0.0f, rollSymbolFactor));
- 縮放變換:物體沿著某個(gè)方向進(jìn)行縮放精绎,物體大小發(fā)生了變化速缨。
glm接口:
Model = glm::scale(Model, glm::vec3(xFactor, yFactor, zFactor));
視圖矩陣
在OpenGL ES我們會(huì)用使用攝像機(jī)代替我們自己作為觀察點(diǎn)觀察物體,攝像機(jī)視角下的空間就是視圖空間代乃,所以視圖矩陣變換和攝像機(jī)的位置有很大關(guān)系旬牲。
glm接口:
View = glm::lookAt(glm::vec3(cx, cy, cz), glm::vec3(tx, ty, tz), glm::vec3(upx, upy, upz));
View 返回的是觀察矩陣
0為偏移量
cx,cy,cz為攝像機(jī)的坐標(biāo)
tx,ty,tz為攝像機(jī)鏡頭方向向量
upx,upy,upz為攝像頭頭方向方向
投影矩陣
OpenGL ES中常用的投影方式有兩種,分別是正交投影與透視投影;
- 正交投影:如圖可以看到原茅,正交投影不會(huì)對遠(yuǎn)處物體進(jìn)行縮放吭历。
glm接口:
Projection = glm::ortho(T left, T right, T bottom, T top, T zNear, T zFar)
- 透視投影:如圖可以看到,透視投影會(huì)對遠(yuǎn)處物體進(jìn)行縮放擂橘,從而產(chǎn)生了“遠(yuǎn)小近大”的現(xiàn)象晌区。
glm接口:
Projection = glm::frustum(T left, T right, T bottom, T top, T nearVal, T farVal)
高級概念
幀緩沖區(qū)(Frame Buffer Object)
簡稱FBO, FBO本身沒有圖像存儲(chǔ)區(qū)。使用時(shí)必須幀緩存關(guān)聯(lián)圖像(紋理或渲染對象)關(guān)聯(lián)到FBO贝室∑踅玻可以理解為畫板仿吞。
頂點(diǎn)緩沖區(qū)(Vertex Buffer Object)
簡稱VBO, VBO是在GPU顯存開辟一個(gè)內(nèi)存空間滑频,用于存放頂點(diǎn)各類屬性信息,包括頂點(diǎn)坐標(biāo)唤冈,頂點(diǎn)法向量峡迷,頂點(diǎn)顏色數(shù)據(jù)等。好處是渲染時(shí)可以直接從顯存讀取頂點(diǎn)屬性信息你虹,不需要從CPU傳入绘搞,效率更高。
頂點(diǎn)數(shù)組緩沖區(qū)(Vertex Array Object)
簡稱VAO, VAO是保存了所有頂點(diǎn)屬性信息VBO的引用傅物,本身不存儲(chǔ)任何頂點(diǎn)信息夯辖。
索引緩沖區(qū)(Element Buffer Object)
簡稱EBO,EBO是在GPU顯存開辟一個(gè)內(nèi)存空間董饰,用于存放所有頂點(diǎn)位置索引indices蒿褂。