這是一篇OpenGL ES的學(xué)習(xí)筆記舀寓,介紹圖像繪制里面用到的概念檀训,學(xué)習(xí)OpenGL ES的基礎(chǔ)知識備忘錄王带。
教程
OpenGLES入門教程1-Tutorial01-GLKit
OpenGLES入門教程2-Tutorial02-shader入門
OpenGLES入門教程3-Tutorial03-三維變換
OpenGLES入門教程4-Tutorial04-GLKit進階
OpenGLES進階教程1-Tutorial05-地球月亮
OpenGLES進階教程2-Tutorial06-光線
OpenGLES進階教程3-Tutorial07-粒子效果
OpenGLES進階教程4-Tutorial08-幀緩存
渲染
用3D數(shù)據(jù)生成一個2D圖像的過程。
數(shù)據(jù)饑餓
CPU擅長運算件炉,讀寫內(nèi)存較慢勘究,當CPU的性能因為等待內(nèi)存讀寫而處于次優(yōu)狀態(tài)時,這種次優(yōu)狀態(tài)就叫做數(shù)據(jù)饑餓斟冕。
為緩存提供數(shù)據(jù)
1口糕、生成(Generate),為緩存生成獨一無二的標識符磕蛇。
2景描、綁定(Bind)十办,確定接下來運算使用的緩存。
3超棺、緩存數(shù)據(jù)(Buffer Data)向族,為綁定的內(nèi)存分配并出示足夠的內(nèi)存,把CPU控制的內(nèi)存數(shù)據(jù)復(fù)制到分配的內(nèi)存棠绘。
4件相、啟用或者禁止(Enable、Disable)氧苍,確定在接下來的渲染是否采用緩存夜矗。
5、設(shè)置指針(Set Pointer)让虐,確定緩存中數(shù)據(jù)的類型和數(shù)據(jù)的偏移值紊撕。
6、繪圖(Draw)澄干,繪制部分或者整個場景逛揩。
7、刪除(Delete)麸俘,刪除生產(chǎn)的緩存并且釋放資源。
緩存的生成惧笛、初始化和刪除从媚,需要耗費時間來同步圖形處理器和CPU。
GPU在刪除一個緩存之前必須等待緩存相關(guān)的運算結(jié)束患整,如果頻繁生成和刪除緩存拜效,GPU沒有足夠時間進行渲染。
數(shù)據(jù)類型
OpenGL ES 坐標是以浮點數(shù)來存儲各谚,GPU對浮點運算做了專門的優(yōu)化紧憾,即使使用其他數(shù)據(jù)類型的頂點也會被轉(zhuǎn)換成浮點型。
圖形處理器本質(zhì)上就是大規(guī)模并行矢量處理器昌渤。
幀緩存
接收渲染結(jié)果的緩沖區(qū)叫做幀緩存赴穗。
有兩個特別的幀緩存,前幀緩存和后幀緩存膀息,控制著屏幕像素的最終顏色般眉。
OpenGL ES的上下文保存了OpenGL ES的狀態(tài)信息,包括用于渲染數(shù)據(jù)的緩存地址和接收渲染結(jié)果的緩存地址潜支。
軟件架構(gòu)
每一個iOS原生控件都有一個對應(yīng)的CoreAnimation層甸赃。
CoreAnimation合成器使用OpenGL ES來盡可能高效地控制GPU、混合層和切換幀緩存冗酿。
OpenGL ES會有連接到層埠对,與層分享數(shù)據(jù)的幀緩存络断,至少包括一個像素顏色渲染緩存。
OpenGL ES函數(shù)
EAGLContext:封裝一個特定于某個平臺的OpenGL ES上下文 實例项玛。
EAGL 可能是 Embedded Apple GLRGBA顏色:紅綠藍和透明度妓羊。(Red、Green稍计、Blue躁绸、Alpha)
glBufferData方法中,GL_STATIC_DRAW告訴上下文臣嚣,緩存中的內(nèi)容適合復(fù)制到GPU控制的內(nèi)存净刮,因為很少對其進行修改;GL_DYNAMIC_DRAW則表示數(shù)據(jù)會頻繁修改硅则,以不同的方式來處理淹父。
幀緩存可能有除了像素顏色渲染緩存之外的其他附加緩存(比如說深度測試),他們可以通過在glClear()函數(shù)中制定不同的參數(shù)來清除怎虫。
glVertextAttribPointer()第四個參數(shù)表示小數(shù)點固定數(shù)據(jù)是否可以被改變暑认。
viewDidUnload在視圖被卸載時候調(diào)用,可以在此刪除OpenGL ES緩存大审。(和dealloc不同)
CAEAGLLyaer是CoreAnimation提供的標準層類之一蘸际,與OpenGL ES的幀緩存共享它的像素顏色倉庫。
context presentRenderbuffer:GL_RENDERBUFFER 讓上下文調(diào)整外觀并使用CoreAnimation合成器把幀緩存的像素顏色渲染緩存與其他相關(guān)層混合起來徒扶。
glViewport() 函數(shù)用來控制渲染至幀緩存的子集粮彤。(設(shè)置視口變換的視口大小)
視圖重新調(diào)整大小的時候姜骡,layoutSubviews會被調(diào)用导坟。
CADisplayLink的消息為重新渲染一個場景提供了理想的觸發(fā)器,渲染速度大于顯示刷新速度是浪費圈澈。
GLKBaseEffect會生成直接在GPU上運行的GLSL惫周。
紋理
一個用來保存圖像顏色的OpenGL ES緩存。
渲染過程中的取樣可能會導(dǎo)致紋理被拉伸康栈、壓縮递递、翻轉(zhuǎn)等。
視口坐標
幀緩存中的像素位置叫做視口坐標谅将。視口轉(zhuǎn)換的結(jié)果是所有繪制的幾何圖形都被拉伸以適應(yīng)屏幕大小漾狼。
光柵化
轉(zhuǎn)換幾何形狀數(shù)據(jù)為幀緩存中的顏色像素,叫做點陣化(rasterizing)饥臂,也叫光柵化逊躁。
每個顏色像素叫做片元(fragment)。
紋理坐標系
glTexParameteri參數(shù)
GL_TEXTURE_MIN_FILTER表示較多紋素對應(yīng)較少片元
GL_TEXTURE_MAG_FILFER表示較多片元對應(yīng)較少紋素
GL_LINEAR 表示線性插值
GL_NEARSET 表示就近選擇當UV坐標超過ST坐標時候
GL_TEXTURE_WRAP_S表示U坐標超過了S坐標
GL_TEXTURE_WRAP_T表示V坐標超過了T坐標
GL_REPEAT 重復(fù)紋理以填滿UV區(qū)域
GL_CLAMP_TO_EDGE 取樣紋理邊緣的紋素
MIP貼圖
高細節(jié)的紋理隅熙,沿著S稽煤、T軸存儲更多的紋素核芽,減少GPU取樣的數(shù)量提高渲染性能,但會增加內(nèi)存酵熙。
glTexImage2D
- 第一個參數(shù)是GL_TEXTURE_2D
- 第二個參數(shù)用于指定MIP貼圖的初始細節(jié)級別轧简,如果沒有使用MIP必須要是0
- 第三個參數(shù)是指定紋理緩存每個紋素需要保存的信息數(shù)量,對于iOS設(shè)備匾二,有GL_RGB和RL_RGBA
- 第四哮独、五個參數(shù)指定圖像的寬度和高度,必須是2的冪
- 第六個 確定紋理紋素的邊界大小察藐,OpenGL ES中總是被設(shè)置為0
- 第七個 指定初始化緩存所用的圖像數(shù)據(jù)中的每個像素要保存的信息皮璧,在OpenGL ES中與inernalFormat
- 第八個 紋素的位編碼類型
- 第九個 像素顏色數(shù)據(jù)的指針
多重紋理
多重紋理可以避免多通道渲染導(dǎo)致的內(nèi)存訪問限制性能情況
self.baseEffect.texture2d1.envMode = GLKTextureEnvModeDecal;
可以開啟多重紋理
光線
- GPU首先為每個三角形的頂點進行光線計算,再把結(jié)果進行插值分飞,得出每個片元的最終顏色悴务。
- OpenGL ES的燈光模擬包括:環(huán)境光、漫反射光譬猫、鏡面反射光讯檐。
- 只有每個光源的環(huán)境光部分才會照射到三角形的后面。
光線與幾何圖形相互作用的關(guān)鍵:計算出每個幾何物體照射和發(fā)散出來多少光線染服。通過計算每個三角形與光的方向的垂直角度别洪。
- 矢量積:右手法則。
VectorA × VectorB 的矢量積 和 B × A 是方向相反的肌索。 - 光線計算依賴于表面法向量蕉拢。法向量也是單位向量。
在GLKBaseEffect的燈光開啟后诚亚,燈光決定了渲染的顏色;常量的顏色和頂點的顏色將被忽略午乓。(constantColor屬性僅適用于渲染單調(diào)不發(fā)光的物體)
- 對于立體表面而言站宗,法線是有方向的:一般來說,由立體的內(nèi)部指向外部的是法線正方向益愈,反過來的是法線負方向梢灭。
- 縮放對燈光有潛在的影響:一個法向量被縮放后,就可能不再是一個單位向量蒸其。
GLKit的GLKBaseEffect類生產(chǎn)的GLSL會按需正規(guī)化法向量敏释。
深度測試
每次渲染一個片元,片元的深度(片元與視點之間的距離)被計算出來并與深度緩存中為片元位置保存的值進行對比:選擇深度值更忻(更接近視點)的片元來钥顽,替換在像素顏色渲染緩存中對應(yīng)位置的顏色和深度緩存的對應(yīng)深度值。
深度緩存為GPU提供了一個存放計算出來深度值的緩存靠汁,并且用來控制像素顏色渲染緩存中片元的置換蜂大。
GLKit支持16位和24位來保存深度值的深度渲染緩存闽铐。深度沖突(Z-fighting),兩個片元的深度非常接近奶浦,深度緩存沒有如果的進度來區(qū)分兄墅,最終的片元顏色經(jīng)常在可能性之間來回閃爍,制造一個可見的干擾澳叉。
不使用GLKit輔助隙咸,管理一個OpenGL ES深度緩存需要的步驟:
1、Generate(生成)—— 生成獨一無二的標識符
2成洗、Bind(綁定)—— 確定使用的緩存
3五督、Configure Storage (配置存儲) —— 指定大小
4、 Attach(附加) —— 附加到一個幀緩存
與一個Core Animation共享內(nèi)存的像素顏色渲染緩存在層調(diào)整大小時會自動調(diào)整大小泌枪。其他緩存概荷,例如深度緩存,不會自動調(diào)整大小碌燕。
可以在layoutSubviews方法里面刪除現(xiàn)存的深度緩存误证,并創(chuàng)建一個新的與像素顏色渲染緩存的新尺寸相匹配的深度緩存。
變換
兩個坐標系之間轉(zhuǎn)換頂點坐標修壕。
-
基本變換
四個基本變換
平移(translation)
旋轉(zhuǎn)(rotation)
縮放(scale)
透視(perspective)
投影變換
視錐體的近平面不能用z位置小于0愈捅,即使是很小的z的值也會有問題。
從近平面到遠平面的距離范圍會映射為深度緩存中的深度范圍慈鸠,當GPU計算保存在深度緩存中的值時蓝谨,大幅度或者過小的近平面距離會產(chǎn)生數(shù)學(xué)舍入誤差。
OpenGL ES使用一個叫做視域的幾何圖形來決定一個場景生成的片元是否會顯示在最終的渲染結(jié)果中青团。
OpenGL ES默認為指入屏幕的負的Z坐標軸譬巫,GLKMatrixMakeFrustum() 產(chǎn)生一個指入屏幕的帶有正的Z坐標軸的視域(view volume)。