1.
深度渲染緩存(Depth Render Buffer)
三角形、線段和點是按它們被GPU處理的順序被渲染的。如果沒有一個深度緩存,為最后一個對象的繪制而產(chǎn)生的片元總是會覆蓋以前渲染的層疊的片元。
視點決定了場景中的哪一個對象會被渲染在其他對象前面。
變換(transformation)使從任意視點渲染場景成為可能。
一個變化的視點必然需要重新計算所繪制對象的正確順序。
深度渲染緩存是一個可選的輸出緩存,與像素顏色渲染緩存相似。
幾乎所有的OpenGLES應(yīng)用都使用深度緩存,因為幾乎所有的OpenGLES應(yīng)用都使用深度緩存,因為幾乎所有的應(yīng)用都使用坐標(biāo)系轉(zhuǎn)換來改變渲染的視點。
在大部分情況下,一個深度緩存會消除對于三角形、線段和點進行排序的需求。
深度緩存也常常叫做Z緩存,因為如果坐標(biāo)系的X軸和Y軸對應(yīng)于屏幕的寬和高,那么Z軸只是的就是屏幕的內(nèi)外。一個片元和視點之間的距離大體相當(dāng)于這個片元沿著Z軸深入屏幕的位置。
GPU把對于每個片元的深度的計算作為渲染的一個固定部分。深度緩存的使用為GPU提供了一個用來保存計算出深度的地方,之后這個深度又被GPU利用來控制在像素顏色渲染緩存中的片元的位置的置換。
2.
利用GLKit添加深度緩存
GLKit支持使用16位或24位來保存深度值的深度渲染緩存。
以上代碼使用了一個變換來矯正拉伸的渲染效果。
GLKMatrix4GLKMatrix4MakeScale(float sx,float sy,float sz)函數(shù),上面代碼中表示會沿著X軸,Z軸保持不變,沿著Y軸的單位長度aspectRatio為(GLfloat)view.drawableWidth/(GLfloat)view.drawableHeight的值,drawableWidth屬性以像素為單位提供了視圖的像素顏色渲染緩存的寬度,與視圖全屏Core Animation相適配。drawableHeight屬性以像素為單位提供了高度。屏幕縱橫比為寬度除以高度。
3.
深入探討不用GLKit添加深度緩存
管理一個深度緩存需要的步驟:
(1)Generate (生成) ——— 告訴OpenGLES為深度緩存生成一個獨一無二的標(biāo)識符。
(2)Bind (綁定) ——— 告訴OpenGLES在接下來的操作中使用哪一個緩存。
(3)Configure Storage(配置存儲) ——— 指定深度緩存的大小
(4)Attach (附加)——— 附加深度緩存到一個幀緩存。
與一個Core Animation層分享內(nèi)存的像素顏色渲染緩存在層調(diào)整大小時會自動調(diào)整大小。其他的緩存,例如深度緩存,并不會自動調(diào)整大小。每當(dāng)一個AGLKView實例被重新調(diào)整大小時,與他相關(guān)聯(lián)的層也會調(diào)整大小并且視圖的-(void)layoutSubviews方法會被調(diào)用。
4.
變換
從數(shù)學(xué)上說,變換就是在兩個坐標(biāo)系之間轉(zhuǎn)換頂點坐標(biāo)。
每個坐標(biāo)系都是相對于其他的參照坐標(biāo)系的。
對于OpenGLES來說,最終的參照坐標(biāo)系實在一個像素顏色渲染緩存中的像素位置的2D數(shù)組。
在渲染過程中,GPU會轉(zhuǎn)換點、線和三角形的頂點坐標(biāo)為著色片元。當(dāng)前(實際上是在GPU處理頂點數(shù)據(jù)時)坐標(biāo)系決定了片元在像素顏色渲染緩存和深度緩存中的位置。
線性代數(shù)可以為坐標(biāo)系間轉(zhuǎn)換提供解決方案。任意數(shù)量任意順序的基本變換都可以能夠被捕獲并保存在一個簡單的4*4的浮點值矩陣中。一個矩陣定義一個坐標(biāo)系。
矩陣計算幾乎完全使用加法和乘法,并且在現(xiàn)代GPU上執(zhí)行的非???。這是好事,因為每次一個場景被渲染時,GPU就會變換所有的頂點,并且在一個場景中常常含有幾十萬個頂點。
5.
基本變換
平移translation、旋轉(zhuǎn)rotation、縮放scale、透視perspective
以上四個基本變換聯(lián)合決定了在一個新坐標(biāo)系中的每一個頂點位置是怎么轉(zhuǎn)換為參考坐標(biāo)系中的一個位置的。
每個基本變換對應(yīng)于矩陣的一個簡單變化。
(1)平移:
通過相對于參考坐標(biāo)系的原點移動新坐標(biāo)系的原點,定義了一個新的坐標(biāo)系。平移不會影響坐標(biāo)軸的單位長度,平移不會改變坐標(biāo)軸相對于參考坐標(biāo)系的方向。
GLKMatrix4GLKMatrix4MakeTranslation(float tx,float ty,float tz)
函數(shù)通過平移一個單位矩陣來返回一個定義了坐標(biāo)系的新矩陣。x、y、z參數(shù)指定了新坐標(biāo)系的原點沿著當(dāng)前參考坐標(biāo)系的每個軸移動的單位數(shù)。
(2)旋轉(zhuǎn):
通過相對于參考坐標(biāo)系坐標(biāo)軸的方向旋轉(zhuǎn)新坐標(biāo)系的坐標(biāo)軸來定義一個新的坐標(biāo)系。旋轉(zhuǎn)的坐標(biāo)系會與參考坐標(biāo)系使用同一個原點。旋轉(zhuǎn)不會影響坐標(biāo)軸的單位長度,只有坐標(biāo)軸的方向會發(fā)生變化。
GLKMatrix4GLKMatrix4MakeRotation(float radians,float x,float y,float z);
函數(shù)通過旋轉(zhuǎn)一個單位矩陣來返回定義了一個坐標(biāo)系的新矩陣。radians參數(shù)指定了要旋轉(zhuǎn)的弧度數(shù)。
(3)縮放:
通過相對于參考坐標(biāo)系的坐標(biāo)系的單位長度改變新坐標(biāo)系的坐標(biāo)軸的單位長度來定義一個新的坐標(biāo)系。縮放的坐標(biāo)系與參考坐標(biāo)系使用同一個原點,坐標(biāo)軸的防線通常不會改變。不過,通過一個負值所做的縮放會反轉(zhuǎn)坐標(biāo)軸的方向。
GLKMatrix4GLKMatrix4MakeScale(floatsx,floatsy,floatsz)
函數(shù)會通過擴大或縮小一個單位矩陣的任意坐標(biāo)軸的單位長度來返回一個定義了坐標(biāo)系的矩陣。x、y、z參數(shù)指定了用來擴大或縮小每個軸的單位長度的因數(shù)。
(4)透視:
透視是通過相對于參考坐標(biāo)軸的單位長度多樣化新坐標(biāo)系的坐標(biāo)軸的單位長度來定義一個新的坐標(biāo)系。透視不會改變坐標(biāo)軸的方向或者原點,但是坐標(biāo)軸的每個單位離原點越遠長度越短。這個效果會讓在遠處的物體比離原點近的物體顯得更小。
GLKMatrix4GLKMatrix4MakeFrustum(float left,float right,float bottom,float top,float nearZ,float farZ);
函數(shù)會透視一個單位矩陣來返回一個定義了坐標(biāo)系的新矩陣。透視坐標(biāo)系的的形狀是一個類似角椎體的平截頭體。
以上為5-4例子中處理基本變幻的代碼。
結(jié)合四大變幻,可以定義新的坐標(biāo)系,不過重要的是變換的順序。平移在旋轉(zhuǎn)的前面還是后面會產(chǎn)生不同的坐標(biāo)系??s放在旋轉(zhuǎn)的前面還是后面也會產(chǎn)生不同的坐標(biāo)系。先旋轉(zhuǎn)再平移最后縮放與先平移再旋轉(zhuǎn)最后縮放是不同的。
5.1
projectionMatrix 和 modelviewMatrix
GLKBaseEffect的transform屬性是一個GLKEffectPropertyTransform類型的實例并為支持常見的操作保存了三個不同的矩陣。
projectionMatrix用于整個場景的坐標(biāo)系。
modelviewMatrix用于控制對象(場景內(nèi)模型)顯示位置的坐標(biāo)系。
GLKBaseEffect會級聯(lián)modelviewMatrix和projectionMatrix以產(chǎn)生一個modelviewProjectionMatrix矩陣,這個矩陣會把對象頂點完全地變換到OpenGLES默認坐標(biāo)系中。
默認坐標(biāo)系直接映射到像素顏色緩存中的片元位置。
5-4例子中在viewDidLoad方法中初始化modelviewMatrix,使用一個明顯的右上視角來渲染對象。
5-4中移動滑塊時,會更新每個用戶用來控制變換的值。首先保存baseEffect的modelviewMatrix的當(dāng)前值,以便加載。然后通過按特定的順序連接當(dāng)前矩陣與用戶控制的三個變換矩陣,這個例子構(gòu)建了一個新的矩陣。
在用戶控制的變換結(jié)合到modelviewMatrix后,為繪制準(zhǔn)備好baseEffect,最后用一個白色的漫反射光繪制場景中的對象。
重新設(shè)置modelviewMatrix為保存的值,燈光顏色改為黃色,再次繪制相同的對象。場景中的黃色對象提供了一個參考,以便可以清楚地觀察用戶控制的變換會怎么影響在最終的像素顏色渲染緩存中的白色對象的哪些片元。
總結(jié):除了使用以上通過臨時變量保存并回復(fù)modelviewMatrix外。GLKit還提供了一個方便的數(shù)據(jù)類型GLKMatrixStack,還提供了一個用來向堆棧數(shù)據(jù)結(jié)構(gòu)保存矩陣的函數(shù)集合。堆棧是一個后進先出的數(shù)據(jù)結(jié)構(gòu),它可以方便地存儲某個程序可能需要回復(fù)的矩陣。
5.2
textureMatrix
以上5-5中代碼顯示了
5-5例子實現(xiàn)了紋理矩陣textureMatrix.
6.
復(fù)合變換手冊
傾斜
是一個復(fù)合變換,這個變換產(chǎn)生了不再相互垂直的坐標(biāo)軸。立方體會變成帶有梯形面的盒子。
圍著一個點旋轉(zhuǎn)
旋轉(zhuǎn)和縮放常常圍繞著當(dāng)前坐標(biāo)系的原點發(fā)生。
圍著一個點縮放
和圍著一個點旋轉(zhuǎn)相似。
7.
透視和平截頭體
OpenGLES使用一個叫做視域(viewing volumn)的幾何圖形來決定一個場景生成的哪些片元將會顯示在最終的渲染結(jié)果中。處于視域范圍之外的幾何圖形都會被剔除,這意味著它會被丟棄。視域有時候也被稱為投影(projection)。
一個立方體或矩形視域叫做一個正攝投影(orthographic)。利用一個正射投影,視點與每個位置之間的距離對于投影毫無影響。
當(dāng)使用投影(perspective projection)時,視域不再是矩形。而是平截頭體。
5-6例子可展現(xiàn)這部分內(nèi)容。
使用視域的另一個關(guān)鍵要認識到,正射和透視投影都是由站在位置{0,0, 0}并向下俯視的z軸的觀察者的視點產(chǎn)生的。本章開頭說變換任意視點稱為可能,但實際上,視點是恒定的。變換會施加到場景中的所有頂點上,并會投影這些頂點到視域的界面上。從概念上看,當(dāng)假設(shè)的觀察者的觀察者的視點不變時,OpenGLES會變換所有的幾何圖形。整個世界移動的錯覺只是看起來像是由視點變換產(chǎn)生的。
總結(jié):
本章介紹了深度緩存、變換、GLKit的矩陣堆棧和視域。實際上本章沒有例子會改變保存在頂點緩存中的頂點的成分。頂點位置保持不變。作為替代,變換改變了頂點被映射到2D像素顏色渲染緩存的方式。