這是一篇OpenGlES 系統(tǒng)學(xué)習(xí)教程矿咕,記錄自己的學(xué)習(xí)過(guò)程技羔。
環(huán)境: Xcode10.2.1 + OpenGL ES 3.0
目標(biāo): 多重紋理喷好、混合
代碼已上傳github
蚀同,Tutorial-05-多重紋理-混合缅刽,你的star和fork是對(duì)我最好的支持和動(dòng)力。
概述
前面教程我們已經(jīng)看到了一個(gè)簡(jiǎn)單的紋理渲染程序蠢络,可能會(huì)發(fā)現(xiàn)這些例子中的一些遺漏之處衰猛。例如:并沒(méi)有設(shè)置片元著色器里采樣器的取值,這是因?yàn)槲覀冎挥玫揭粋€(gè)紋理刹孔,從而使用了默認(rèn)紋理單元啡省。
紋理單元
紋理單元的主要目的是讓我們?cè)谥髦锌梢允褂枚嘤谝粋€(gè)的紋理。通過(guò)把紋理單元賦值給采樣器髓霞,我們可以一次綁定多個(gè)紋理卦睹,只要我們首先激活對(duì)應(yīng)的紋理單元。就像glBindTexture
一樣方库,我們可以使用glActiveTexture
激活紋理單元分预,傳入我們需要使用的紋理單元:
glActiveTexture(GLenum(GL_TEXTURE0)) // 激活紋理單元
glBindTexture(GLenum(GL_TEXTURE_2D), tex1) // 綁定紋理到指定紋理單元
glUniform1i(tex1_loc, 0) // 給采樣器分配位置值
激活紋理單元之后,接下來(lái)的glBindTexture函數(shù)調(diào)用會(huì)綁定這個(gè)紋理到當(dāng)前激活的紋理單元薪捍,紋理單元GL_TEXTURE0默認(rèn)總是被激活笼痹,所以我們?cè)谇懊娴睦永锂?dāng)我們使用glBindTexture的時(shí)候配喳,無(wú)需激活任何紋理單元。
事實(shí)上凳干,OpenGL可以同時(shí)支持很多個(gè)紋理晴裹。一個(gè)著色器階段至少支持16個(gè)紋理,如果乘以O(shè)penGL支持的著色器階段的數(shù)量那就是80個(gè)紋理了救赐!而實(shí)際上涧团,OpenGL確實(shí)有80個(gè)紋理單元,它們對(duì)應(yīng)于標(biāo)識(shí)符GL_TEXTURE0 ~ GL_TEXTURE79)经磅。
使用多重紋理時(shí)泌绣,我們需要定義多個(gè)uniform類型的采樣器變量。每個(gè)變量都對(duì)應(yīng)著一個(gè)不同的紋理單元预厌。從應(yīng)用程序的角度來(lái)說(shuō)阿迈, 采樣器uniform和一般的整數(shù)uniform非常類似。它們可以使用通常的glGetActiveUniform()函數(shù)來(lái)進(jìn)行枚舉轧叽,也可以使用glUniformli()函數(shù)來(lái)設(shè)置紋理單元位置值苗沧。
我們需要編輯片段著色器來(lái)接收多個(gè)采樣器。如下:
varying lowp vec2 tex_coord;
uniform sampler2D tex1;
uniform sampler2D tex2;
void main(void)
{
gl_FragColor = mix(texture2D(tex1,tex_coord),texture2D(tex2,tex_coord), 0.2);
}
最終輸出顏色現(xiàn)在是兩個(gè)紋理的結(jié)合炭晒。GLSL內(nèi)建的mix
函數(shù)需要接受兩個(gè)值作為參數(shù)待逞,并對(duì)它們根據(jù)第三個(gè)參數(shù)進(jìn)行線性插值。如果第三個(gè)值是0.0
网严,它會(huì)返回第一個(gè)輸入识樱;如果是1.0
,會(huì)返回第二個(gè)輸入值震束。0.2
會(huì)返回80%
的第一個(gè)輸入顏色和20%
的第二個(gè)輸入顏色牺荠,即返回兩個(gè)紋理的混合色。
主要是使用glUniform1i
設(shè)置每個(gè)采樣器的對(duì)應(yīng)哪個(gè)紋理單元驴一。下面看渲染過(guò)程:
glClearColor(0.0, 1.0, 0.0, 1.0)
glClear(GLbitfield(GL_COLOR_BUFFER_BIT))
glViewport(0, 0, GLsizei(frame.size.width), GLsizei(frame.size.height))
// 第一個(gè)紋理
glActiveTexture(GLenum(GL_TEXTURE0)) // 激活紋理單元
glBindTexture(GLenum(GL_TEXTURE_2D), tex1) // 綁定紋理到指定紋理單元
glUniform1i(tex1_loc, 0) // 給采樣器分配位置值
// 第二個(gè)紋理
glActiveTexture(GLenum(GL_TEXTURE1))
glBindTexture(GLenum(GL_TEXTURE_2D), tex2)
glUniform1i(tex2_loc, 1)
glDrawArrays(GLenum(GL_TRIANGLES), 0, GLsizei(vertCount));
myContext?.presentRenderbuffer(Int(GL_RENDERBUFFER))
效果如下:
混合
為了渲染出不同的透明度級(jí)別休雌,我們需要開啟混合(Blending)
OpenGLES 混合的方式:
例如:我把綠色物體
渲染到紅色物體
上,那么此時(shí)目標(biāo)顏色是紅色
肝断,源顏色是綠色
杈曲。至于因子
,先設(shè)置源因子就是源向量的Alpha
值胸懈,然后目標(biāo)因子是1.0-源因子
担扑。
void glBlendFunc(GLenum sfactor, GLenum dfactor)
接收兩個(gè)參數(shù)用來(lái)設(shè)置源(source)
和目標(biāo)(destination)
因子。其中參數(shù)選項(xiàng)如下:
由于開啟混合我們只需要一個(gè)紋理單位趣钱,前后兩次繪制涌献。片段著色器如下:
varying lowp vec2 tex_coord;
uniform sampler2D tex1;
void main(void)
{
gl_FragColor = texture2D(tex1,tex_coord);
}
渲染過(guò)程如下:
glClearColor(0.0, 1.0, 0.0, 1.0)
glClear(GLbitfield(GL_COLOR_BUFFER_BIT))
glViewport(0, 0, GLsizei(frame.size.width), GLsizei(frame.size.height))
// 關(guān)閉第一個(gè)紋理混合
glDisable(GLenum(GL_BLEND))
glActiveTexture(GLenum(GL_TEXTURE0))
glBindTexture(GLenum(GL_TEXTURE_2D), tex1)
glUniform1i(tex1_loc, 0)
// 繪制第一個(gè)紋理
glDrawArrays(GLenum(GL_TRIANGLES), 0, GLsizei(vertCount));
// 開啟第二個(gè)紋理混合
glEnable(GLenum(GL_BLEND));
// 設(shè)置混合因子
glBlendFunc(GLenum(GL_ONE), GLenum(GL_ONE));
glActiveTexture(GLenum(GL_TEXTURE1))
glBindTexture(GLenum(GL_TEXTURE_2D), tex2)
glUniform1i(tex1_loc, 1)
// 繪制第二個(gè)紋理
glDrawArrays(GLenum(GL_TRIANGLES), 0, GLsizei(vertCount));
myContext?.presentRenderbuffer(Int(GL_RENDERBUFFER))
效果如下:
參考
- OpenGL編程指南(第9版)
- LearnOpenGL教程的中文翻譯