什么是紋理
紋理是一個(gè)用來(lái)保存圖像的顏色色素值得OpenGL ES緩存, 紋理的作用是為了使我們渲染的幾何圖像更加的逼真, 通常來(lái)說(shuō)就是使用一張圖片貼在我們需要渲染的幾何圖形上.
當(dāng)一個(gè)圖像初始化一個(gè)紋理緩存之后, 在這個(gè)圖像中的每個(gè)像素就變成了紋素(texel), 紋素也是用來(lái)保存顏色數(shù)據(jù)的.
紋理坐標(biāo)
紋理坐標(biāo)是一個(gè)命名為S和T的2D軸, 在一個(gè)紋理坐標(biāo)中, 無(wú)論紋素有多少個(gè), 在紋理的尺寸永遠(yuǎn)是S軸上從0.0到1 .0, 在T軸上從0.0到1.0. 紋理坐標(biāo)是一個(gè)相對(duì)坐標(biāo)的概念.
例如, 從一個(gè)1像素高, 64像素寬的圖像初始化來(lái)的紋理會(huì)沿著T軸有一個(gè)紋素, 沿著S軸有64個(gè)紋素.
轉(zhuǎn)換幾何形狀數(shù)據(jù)為幀緩存中的顏色像素的渲染步驟叫做點(diǎn)陣化(rasterizing), 每個(gè)顏色像素叫做(fragment). 當(dāng)OpenGL ES沒有使用紋理時(shí), GPU會(huì)根據(jù)包含該片元的對(duì)象的頂點(diǎn)的顏色來(lái)計(jì)算每個(gè)片元的顏色, 當(dāng)設(shè)置了紋理之后, GPU會(huì)根據(jù)當(dāng)前綁定的紋理緩存中的紋素來(lái)計(jì)算每個(gè)片元的顏色.
其實(shí)紋理就是要把一張圖片貼在我們繪制的幾何圖像上, 我們要制定貼在哪個(gè)位置, 這時(shí)就需要用到OpenGL ES坐標(biāo)與紋理坐標(biāo)之間的轉(zhuǎn)化.
我的理解是紋理坐標(biāo)是一個(gè)相對(duì)的坐標(biāo), 是相對(duì)與OpenGL ES的坐標(biāo)
在OpenGL ES之繪制三角形(一)一節(jié)中, 我們繪制三角形需要指定三角形的頂點(diǎn)位置, 同樣, 我們繪制紋理, 也需要指定紋素的位置
typedef struct {
GLKVector3 positionCoords;
GLKVector2 textureCoords;
}
SceneVertex;
在原先的結(jié)構(gòu)體中新增一個(gè)類型GLKVector2
, 用于存儲(chǔ)紋理的坐標(biāo)數(shù)據(jù)
static const SceneVertex vertices[] =
{
{{-0.5f, -0.5f, 0.0f}, {0.0f, 0.0f}},
{{ 0.5f, -0.5f, 0.0f}, {1.0f, 0.0f}},
{{-0.5f, 0.5f, 0.0f}, {0.0f, 1.0f}},
};
頂點(diǎn)坐標(biāo){-0.5f, -0.5f, 0.0f}映射到紋理坐標(biāo)就變?yōu)閧0.0f, 0.0f}, 頂點(diǎn)左下角的坐標(biāo)對(duì)應(yīng)紋理的左下角, 然后依次向S軸和T軸延伸到1.
接下來(lái)就是開始渲染紋理
// Setup texture
CGImageRef imageRef = [[UIImage imageNamed:@"leaves.gif"] CGImage];
GLKTextureInfo *textureInfo = [GLKTextureLoader
textureWithCGImage:imageRef
options:nil
error:NULL];
self.baseEffect.texture2d0.name = textureInfo.name;
self.baseEffect.texture2d0.target = textureInfo.target;
textureWithCGImage
方法, 把CGImageRef轉(zhuǎn)成GLKTextureInfo
類型的紋理緩存, GLKTextureInfo
類保存了紋理緩存的信息, target屬性指定被配置的紋理緩存的類型, name是紋理緩存的一個(gè)標(biāo)識(shí)符.
至此紋理就被成功的渲染出來(lái)了.
混合
我們都知道三原色是紅, 黃, 藍(lán), 通過(guò)這三種顏色可以調(diào)配出其他的顏色滴铅。
混合就是把兩種顏色通過(guò)某種特定的方式混在一起橡淆。實(shí)現(xiàn)特殊的效果。就是透過(guò)一個(gè)物體去看另外一個(gè)物體的模式, 如果遮擋物是透明的, Alpha為0, 則我們可以透過(guò)遮擋物去看到被遮擋的物體, 就像玻璃一樣, 你可以透過(guò)玻璃去看到玻璃里面的東西; 如果遮擋物不是透明的, Alpha為1, 你就看不到被遮擋的物體, 就像你不能透過(guò)一堵墻去看墻另一側(cè)的物體.
要使用OpenGL的混合功能准脂,只需要調(diào)用:glEnable(GL_BLEND)
即可良风。
要關(guān)閉OpenGL的混合功能脆炎,只需要調(diào)用:glDisable(GL_BLEND)
即可踏拜。
注意:只有在RGBA模式下,才可以使用混合功能荚虚,顏色索引模式下是無(wú)法使用混合功能的薛夜。
混合需要把原來(lái)的顏色和將要畫上去的顏色找出來(lái),經(jīng)過(guò)某種方式處理后得到一種新的顏色版述。這里把將要畫上去的顏色稱為“源顏色”梯澜,把原來(lái)的顏色稱為“目標(biāo)顏色”。
OpenGL 會(huì)把源顏色和目標(biāo)顏色各自取出渴析,并乘以一個(gè)系數(shù)(源顏色乘以的系數(shù)稱為“源因子”晚伙,目標(biāo)顏色乘以的系數(shù)稱為“目標(biāo)因子”),然后進(jìn)項(xiàng)數(shù)學(xué)運(yùn)算, 這樣就得到了新的顏色俭茧。
源因子和目標(biāo)因子是可以通過(guò)glBlendFunc
函數(shù)來(lái)進(jìn)行設(shè)置的咆疗。glBlendFunc
有兩個(gè)參數(shù),前者表示源因子母债,后者表示目標(biāo)因子午磁。這兩個(gè)參數(shù)可以是多種值,下面介紹比較常用的幾種毡们。
GL_ZERO: 表示使用0.0作為因子迅皇,實(shí)際上相當(dāng)于不使用這種顏色參與混合運(yùn)算创泄。
GL_ONE: 表示使用1.0作為因子籍铁,實(shí)際上相當(dāng)于完全的使用了這種顏色參與混合運(yùn)算江兢。
GL_SRC_ALPHA:表示使用源顏色的alpha值來(lái)作為因子照激。
GL_DST_ALPHA:表示使用目標(biāo)顏色的alpha值來(lái)作為因子。
GL_ONE_MINUS_SRC_ALPHA:表示用1.0減去源顏色的alpha值來(lái)作為因子扣囊。
GL_ONE_MINUS_DST_ALPHA:表示用1.0減去目標(biāo)顏色的alpha值來(lái)作為因子吉嫩。
舉例來(lái)說(shuō):
- 如果設(shè)置了glBlendFunc(GL_ONE, GL_ZERO);其掂,則表示完全使用源顏色脖隶,完全不使用目標(biāo)顏色扁耐,因此畫面效果和不使用混合的時(shí)候一致(當(dāng)然效率可能會(huì)低一點(diǎn)點(diǎn))。如果沒有設(shè)置源因子和目標(biāo)因子产阱,則默認(rèn)情況就是這樣的設(shè)置婉称。
- 如果設(shè)置了glBlendFunc(GL_ZERO, GL_ONE);,則表示完全不使用源顏色构蹬,因此無(wú)論你想畫什么王暗,最后都不會(huì)被畫上去了。(但這并不是說(shuō)這樣設(shè)置就沒有用庄敛,有些時(shí)候可能有特殊用途)
- 如 果設(shè)置了glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);俗壹,則表示源顏色乘以自身的alpha 值,目標(biāo)顏色乘以1.0減去源顏色的alpha值藻烤,這樣一來(lái)绷雏,源顏色的alpha值越大,則產(chǎn)生的新顏色中源顏色所占比例就越大怖亭,而目標(biāo)顏色所占比例則減 小涎显。這種情況下,我們可以簡(jiǎn)單的將源顏色的alpha值理解為“不透明度”兴猩。這也是混合時(shí)最常用的方式期吓。
- 如果設(shè)置了glBlendFunc(GL_ONE, GL_ONE);,則表示完全使用源顏色和目標(biāo)顏色倾芝,最終的顏色實(shí)際上就是兩種顏色的簡(jiǎn)單相加讨勤。例如紅色(1, 0, 0)和綠色(0, 1, 0)相加得到(1, 1, 0),結(jié)果為黃色蛀醉。
注意:
所 謂源顏色和目標(biāo)顏色悬襟,是跟繪制的順序有關(guān)的。假如先繪制了一個(gè)紅色的物體拯刁,再在其上繪制綠色的物體脊岳。則綠色是源顏色,紅色是目標(biāo)顏色垛玻。如果順序反過(guò)來(lái)割捅,則 紅色就是源顏色,綠色才是目標(biāo)顏色帚桩。在繪制時(shí)亿驾,應(yīng)該注意順序,使得繪制的源顏色與設(shè)置的源因子對(duì)應(yīng)账嚎,目標(biāo)顏色與設(shè)置的目標(biāo)因子對(duì)應(yīng)莫瞬。不要被混亂的順序搞暈 了儡蔓。
在上面的代碼中我們已經(jīng)完成了單個(gè)紋理的實(shí)現(xiàn), 現(xiàn)在我們?cè)偬砑右粋€(gè)紋理, 來(lái)實(shí)現(xiàn)多重混合
設(shè)置坐標(biāo), 兩個(gè)三角形, 組成一個(gè)矩形
static const SceneVertex vertices[] =
{
//第一個(gè)三角形
{{-1.0f, -0.5f, 0.0f}, {0.0f, 0.0f}}, // first triangle
{{ 1.0f, -0.5f, 0.0f}, {1.0f, 0.0f}},
{{-1.0f, 0.5f, 0.0f}, {0.0f, 1.0f}},
//第二個(gè)三角形
{{ 1.0f, -0.5f, 0.0f}, {1.0f, 0.0f}}, // second triangle
{{-1.0f, 0.5f, 0.0f}, {0.0f, 1.0f}},
{{ 1.0f, 0.5f, 0.0f}, {1.0f, 1.0f}},
};
前面說(shuō)過(guò)OpenGL ES 采用的是世界坐標(biāo)系, 世界坐標(biāo)系以屏幕中心為原點(diǎn)(0, 0, 0)。你面對(duì)屏幕疼邀,你的右邊是x正軸喂江,上面是y正軸,屏幕指向你的為z正軸旁振。長(zhǎng)度單位這樣來(lái)定: 窗口范圍按此單位恰好是(-1,-1)到(1,1)获询。
通過(guò)此坐標(biāo)系渲染之后將是一個(gè)矩形, 但是實(shí)際上是有兩個(gè)三角形組成的矩形
//紋理 texture0
CGImageRef imageRef0 =
[[UIImage imageNamed:@"leaves.gif"] CGImage];
self.textureInfo0 = [GLKTextureLoader
textureWithCGImage:imageRef0
options:[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES],
GLKTextureLoaderOriginBottomLeft, nil]
error:NULL];
// 紋理 texture1
CGImageRef imageRef1 =
[[UIImage imageNamed:@"beetle.png"] CGImage];
self.textureInfo1 = [GLKTextureLoader
textureWithCGImage:imageRef1
options:[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES],
GLKTextureLoaderOriginBottomLeft, nil]
error:NULL];
//GLKTextureLoaderOriginBottomLeft 設(shè)置成YES
//開啟混合
glEnable(GL_BLEND);
//設(shè)置源因子與目標(biāo)因子的關(guān)系
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
我們現(xiàn)在設(shè)置了兩個(gè)紋理, 所以當(dāng)我們繪制的時(shí)候也需要分別進(jìn)行繪制, 此處注意, 紋理顯示的先后順序是根據(jù)繪制的先后順訊決定的. 先繪制的在下面, 后繪制的在上面, 這個(gè)和UIView的層級(jí)結(jié)構(gòu)是一樣的.
在- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
方法里進(jìn)行繪制, 這些方法也可以寫在設(shè)置設(shè)置紋理的時(shí)候
self.baseEffect.texture2d0.name = self.textureInfo0.name;
self.baseEffect.texture2d0.target = self.textureInfo0.target;
self.baseEffect.texture2d0.name = self.textureInfo1.name;
self.baseEffect.texture2d0.target = self.textureInfo1.target;
混合就是在繪制時(shí),不是直接把新的顏色覆蓋在原來(lái)舊的顏色上拐袜,而是將新的顏色與舊的顏色經(jīng)過(guò)一定的運(yùn)算吉嚣,從而產(chǎn)生新的顏色。新的顏色稱為源顏色蹬铺,原來(lái)舊的顏色稱為目標(biāo)顏色尝哆。傳統(tǒng)意義上的混合,是將源顏色乘以源因子丛塌,目標(biāo)顏色乘以目標(biāo)因子较解,然后相加。
源 因子和目標(biāo)因子是可以設(shè)置的赴邻。源因子和目標(biāo)因子設(shè)置的不同直接導(dǎo)致混合結(jié)果的不同印衔。將源顏色的alpha值作為源因子,用1.0減去源顏色alpha值作 為目標(biāo)因子姥敛,是一種常用的方式奸焙。這時(shí)候,源顏色的alpha值相當(dāng)于“不透明度”的作用彤敛。利用這一特點(diǎn)可以繪制出一些半透明的物體与帆。
在進(jìn)行混合時(shí),繪制的順序十分重要墨榄。因?yàn)樵诶L制時(shí)玄糟,正要繪制上去的是源顏色,原來(lái)存在的是目標(biāo)顏色袄秩,因此先繪制的物體就成為目標(biāo)顏色阵翎,后來(lái)繪制的則成為源顏色。繪制的順序要考慮清楚之剧,將目標(biāo)顏色和設(shè)置的目標(biāo)因子相對(duì)應(yīng)郭卫,源顏色和設(shè)置的源因子相對(duì)應(yīng)。