前言
最近觀看下面這本書有感,結(jié)合之前的學(xué)習(xí),對OpenGL的知識進(jìn)行回顧。

概念
幀緩存:接收渲染結(jié)果的緩沖區(qū),為GPU指定存儲渲染結(jié)果的區(qū)域。
幀緩存可以同時存在多個,但是屏幕顯示像素受到保存在前幀緩存(front frame buffer)的特定幀緩存中的像素顏色元素的控制。
程序的渲染結(jié)果通常保存在后幀緩存(back frame buffer)在內(nèi)的其他幀緩存,當(dāng)渲染后的后幀緩存完成后,前后幀緩存會互換。(這部分操作由操作系統(tǒng)來完成)
前幀緩存決定了屏幕上顯示的像素顏色,會在適當(dāng)?shù)臅r候與后幀緩存切換。
- (BOOL)presentRenderbuffer:(NSUInteger)target;
Core Animation的合成器會聯(lián)合OpenGL ES層和UIView層、StatusBar層等,在后幀緩存混合產(chǎn)生最終的顏色,并切換前后幀緩存;
OpenGL ES坐標(biāo)是以浮點(diǎn)數(shù)來存儲,即使是其他數(shù)據(jù)類型的頂點(diǎn)數(shù)據(jù)也會被轉(zhuǎn)化成浮點(diǎn)型;
framebuffer object 通常也被稱之為 FBO,它相當(dāng)于 buffer(color, depth, stencil)的管理者,三大buffer 可以附加到一個 FBO 上。我們是用 FBO 來在 off-screen buffer上進(jìn)行渲染。
GPU運(yùn)算和CPU運(yùn)算是分開的。(如果需要同步返回,可以使用glFinish)
glReadPixels 從圖形硬件中復(fù)制數(shù)據(jù),通常通過總線傳輸?shù)较到y(tǒng)內(nèi)存。此時,應(yīng)用程序?qū)⒈蛔枞?,直到?nèi)存?zhèn)鬏斖瓿伞?br>
如果指定的像素布局與圖像硬件的本地排列不同,數(shù)據(jù)進(jìn)行重定格式會產(chǎn)生額外的性能開銷。
在使用完緩存后,可以調(diào)用glBindBuffer把a(bǔ)rray綁定的對象重置為0,防止被其他地方誤用;(注意,紋理對象需要在使用完后,再glBindTexture綁定為0)
CAEAGLLayer會與OpenGL ES的幀緩存共享它的像素顏色倉庫。(這也是為什么我們想讓繪制的內(nèi)容顯示到屏幕時,需要重載UIView的+layerClass方法,返回一個CAEAGLLayer實(shí)例。)
eaglLayer的屬性kEAGLDrawablePropertyRetainedBacking為NO表示,不要試圖保留任何以前繪制的圖像留作以后重用。
在自定義UIView實(shí)現(xiàn)渲染時,需要在調(diào)整視圖大小的回調(diào)中(layoutSubviews),調(diào)用-renderbufferStorage:fromDrawable: 方法來調(diào)整視圖的尺寸,從而匹配層的新尺寸。
這個尺寸大小可以用glGetRenderbufferParameteriv()方法來獲?。?br>
glGetError返回錯誤,如果有多個錯誤,每次返回一個,需要多次調(diào)用。
CoreGraphics負(fù)責(zé)創(chuàng)建顯示到屏幕上的數(shù)據(jù)模型,QuartzCore(CoreAnimation –> OpenGLES)負(fù)責(zé)把CoreGraphics創(chuàng)建的數(shù)據(jù)模型真正顯示到屏幕上。
理想狀態(tài)下,緩存生成后就不發(fā)生變化;
生成、初始化和刪除緩存需要耗費(fèi)時間來同步GPU和CPU,大多數(shù)情況下是CPU等待GPU,因為GPU在刪除緩存之前必須等待該緩存相關(guān)的指令全部執(zhí)行完畢;
故而一個程序在每幀都進(jìn)行生成和刪除緩存會有嚴(yán)重的性能消耗。
glDeleteFramebuffers
glDeleteRenderbuffers
glDeleteBuffers
坐標(biāo)
齊次坐標(biāo)表示法:用n+1維向量表示n維向量。
齊次坐標(biāo)歸一化,最后一個坐標(biāo)為1。
If set to GL_TRUE, normalized indicates that values stored in an integer format are to be mapped to the range [-1,1]
整數(shù)才能歸一化,浮點(diǎn)數(shù)無效。

萬向節(jié)死鎖:Wiki解釋
如果是用高度角和偏航角來解釋,就是當(dāng)高度角等于90°的時候,偏航角的維度已經(jīng)丟失,不管你怎么轉(zhuǎn)都不會產(chǎn)生結(jié)果。
Gimbal_lock不是說空間存在某個點(diǎn)無法用極坐標(biāo)的方式來表示,而是點(diǎn)的運(yùn)動不能用連續(xù)的極坐標(biāo)來表示。
紋理
紋理坐標(biāo)系:S和T組成的2D軸。(0.0到1.0,還有1D和3D的紋理坐標(biāo)系,R,S,T軸)
位圖(bitmap):一系列表示開啟和關(guān)閉像素值的0和1。
像素數(shù)據(jù) != 位圖。
像素圖(pixmap):類似位圖,每個像素需要一個以上的存儲位來表示。
The more general term pixmap refers to a map of pixels, where each one may store more than two colors, thus using more than one bit per pixel. Often bitmap is used for this as well. In some contexts, the term bitmap implies one bit per pixel, while pixmap is used for images with multiple bits per pixel.
圖像數(shù)據(jù)在內(nèi)存中很少以緊密的形式存在,出于性能的考慮,每一行都該從特定的字節(jié)對齊地址開始。
OpenGL 采用4個字節(jié)的對齊方式。
存儲大小 != 像素寬度 * 高度值。
應(yīng)該是每行寬度 * 高度值,每行寬度可能會有填充的空字節(jié)。
1、紋理過濾
GL_TEXTURE_MIN_FILTER 表示多個紋素對應(yīng)單個像素的時候
GL_TEXTURE_MAG_FILTER表示單個紋素對應(yīng)多個像素的時候
GL_LINEAR 表示線性插值
GL_NEAREST 表示最近
2、紋理環(huán)繞
GL_TEXTURE_WRAP_S 表示S軸超過坐標(biāo)系范圍
GL_TEXTURE_WRAP_T 表示T軸超過坐標(biāo)系范圍
GL_CLAMP_TO_EDGE 表示取紋理邊緣
GL_REPEAT 表示重復(fù)紋理
GL_MIRRORED_REPEAT 表示鏡像重復(fù)紋理
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
OpenGL ES推薦使用尺寸為2的冪的紋理,其他紋理也支持,但是性能上會有額外的消耗。
3、各向異性過濾
非OpenGL標(biāo)準(zhǔn)的擴(kuò)展支持,GL_EXT_texture_filter_anisotropic。
4、MIP紋理
glGenerateMipmap生成。
MIP紋理會比普通大33%,計算公式如下:
1 + 1/4 + 1/16 + 1/64 ... + 1/(4^n)
根據(jù)等比求和公式得到Sn = 1+1/3
glPixelStorei 方法可以改變或者恢復(fù)像素的存儲方式
GL_PACK_ALIGNMENT
GL_UNPACK_ALIGNMENT
默認(rèn)4字節(jié)對齊,即一行的圖像數(shù)據(jù)字節(jié)數(shù)必須是4的整數(shù)倍,即讀取數(shù)據(jù)時,讀取4個字節(jié)用來渲染一行,之后讀取4字節(jié)數(shù)據(jù)用來渲染第二行。對RGB 3字節(jié)像素而言,若一行10個像素,即30個字節(jié),在4字節(jié)對齊模式下,OpenGL會讀取32個字節(jié)的數(shù)據(jù),若不加注意,會導(dǎo)致glTextImage中致函數(shù)的讀取越界崩潰。
One value affects the packing of pixel data into memory: GL_PACK_ALIGNMENT
. The other affects the unpacking of pixel data from memory: GL_UNPACK_ALIGNMENT
https://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml
默認(rèn)是4字節(jié)讀取。
當(dāng)著色器計算出來一個完全不透明的像素顏色時,可以簡單的替換幀緩存中對應(yīng)位置的顏色,也可以通過glEnable(GL_BLEND)來開啟混合功能,并通過glBlendFunc設(shè)置混合函數(shù)。
也可以通過gl_LastFragData,自己計算混合后的顏色;
也可以通過多重紋理來實(shí)現(xiàn)。
多通道渲染:多次讀寫像素顏色緩存來創(chuàng)建一個最終的渲染結(jié)果的過程;
(舉例:開啟混合,只有紋理單元0,先綁定為紋理1,繪制;再綁定紋理2,繪制;再綁定紋理3,繪制;這樣得到最后的結(jié)果,是3張圖片混合后的結(jié)果)
glTexImage2D (1D和3D在ES2的頭文件沒找到,3D可以在ES3找到)加載紋理,紋理對象需要通過glGenTexture和glDelete 來創(chuàng)建和銷毀。
glTexSubImage2D 是替換紋理,可以替換部分,也可以替換全部紋理,速度比重新加載更快。
glCopyTexImage2D 可以用顏色緩沖區(qū)加載數(shù)據(jù)。
glCopyTexSubImage2D 同上。
在銷毀紋理的時候,如果不確定對象索引是否是紋理(比如作為參數(shù)傳遞),glIsTexture來判斷。
紋理高級知識
1、矩形紋理
GL_TEXTURE_RECTANGLE不能進(jìn)行MIP貼圖,只能加載glTexImage2D的第0層。 紋理坐標(biāo)不是標(biāo)準(zhǔn)化的,紋理坐標(biāo)實(shí)際上是對像素尋址,而不是從0到1的范圍覆蓋圖像的。
紋理坐標(biāo)(5,19)實(shí)際上是圖像中從左起6個像素以及從上面起第20個像素。
2、立方體紋理
由6個正方形的2D圖像組成的紋理。
3、多重紋理
同時使用兩個或者更多紋理。
4、點(diǎn)塊紋理
在一個頂點(diǎn)上應(yīng)用紋理。
紋理數(shù)組、紋理代理略。
基本圖形光柵化
1、直線
暴力法:微分方程,帶入坐標(biāo),取整求解(x,y);
中點(diǎn)畫線法:假設(shè)斜率在0~1之間,對于P(x, y),下一個點(diǎn)只能在P1或者P2,求P1P2中點(diǎn)M,直線與P1P2交點(diǎn)Q,判斷M、Q的上下關(guān)系;
bresenham畫線法:假設(shè)斜率在0~1之間,對于P(x, y),下一個點(diǎn)只能在P1或者P2,直線與P1P2交點(diǎn)為Q,判斷P1Q和QP2的大小關(guān)系;
2、圓
圓具有八對稱性,對于一個愿只需要繪制1/8的圓弧;
圓的bresenham,用D(P)來表示點(diǎn)P到原點(diǎn)的距離平方和圓的半徑平方之差,
di = D(Si) + D(Ti)。
超級寶典遇到的問題
1、gltReadTGABits錯誤
因為沒有引入頭文件和對應(yīng)的cpp文件。
2、Invalid storage qualifiers 'in' in global variable context
改成 attribute 和 varying
3、不支持的version
以下是對應(yīng)的GLSL版本
