從0開始的OpenGL學(xué)習(xí)(六)-顯示不同的紋理

本文主要解決2個問題:

1、不同格式的圖片,如何作為紋理使用(png妄帘、bmp)获列?
2、兩張紋理如何進行融合操作,并且通過融合因子去調(diào)整顯示效果?

一、不同格式的圖片闪朱,如何作為紋理使用(png、bmp)钻洒?

1.1 png格式

不管三七二十一奋姿,直接把圖片替換掉,看看效果素标。

直接把圖替換為png圖片

嗯称诗?這詭異的顯示是啥?

第一反應(yīng)头遭,某些參數(shù)設(shè)置出錯粪狼,尤其是glTexImage2D函數(shù)退腥。直接瞄準參數(shù)GL_RGB,png圖片有度的信息再榄,所以格式應(yīng)該設(shè)置為GL_RGBA才對狡刘。想明白了,馬上修改試試困鸥。

修改成GL_RGBA之后

不出所料嗅蔬!

1.2 bmp格式

還是那樣,先直接改文件看效果疾就。

換成bmp格式的文件

不對啊澜术,bmp格式不是有透明通道嗎?怎么回事猬腰?來檢查一下圖片的屬性鸟废。

圖片屬性

哦,原來位深度只有24姑荷,也就是只有RGB三個通道了盒延。把格式換回GL_RGB應(yīng)該沒問題了。

換回GL_RGB格式之后的顯示

對的鼠冕,我們分析地沒錯添寺。那么問題來了,難道我們需要一張張查看圖片的屬性來設(shè)置這個格式嗎懈费?這也太復(fù)雜了计露,或者根據(jù)圖片的后綴確定用什么參數(shù)。要是相同后綴的圖片有不同格式咋辦憎乙?

4通道bmp圖片

沒有開玩笑哦票罐,這樣的圖片還是很常見的。

仔細看看代碼泞边,原來我們在加載圖片的時候已經(jīng)讀取出通道數(shù)量了该押,保存在nrChannels變量中。這樣就方便多了繁堡!我們完全可以根據(jù)通道數(shù)量來設(shè)置格式沈善。簡單點乡数,直接用一行代碼搞定:

GLint format = nrChannels == 3 ? GL_RGB : GL_RGBA;

然后在調(diào)用的時候就可以用format變量了椭蹄。

glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);

效果圖:

效果圖

工程源碼:http://pan.baidu.com/s/1mh6oQMW

二、兩張紋理如何進行融合操作净赴,并且通過融合因子去調(diào)整顯示效果绳矩?

2.1 紋理單元

細心的你可能早就發(fā)現(xiàn)了,我們之前的使用紋理采樣的時候玖翅,并沒有對片元著色器中的采樣器進行賦值翼馆,但顯示的效果確實正確的割以。為什么呢?

這里就要引出一個紋理單元的概念应媚。什么是紋理單元严沥,說實話,筆者也沒有找到確切的定義中姜,只知道紋理是通過紋理單元這個東西綁定到OpenGL環(huán)境中的消玄。根據(jù)筆者的理解,紋理單元應(yīng)該是OpenGL中內(nèi)置的關(guān)于紋理的一些配置丢胚,OpenGL會根據(jù)這些配置來操作紋理翩瓜。在OpenGL中,紋理單元的數(shù)量至少有16個携龟,我們可以通過GL_TEXTURE0...GL_TEXTURE15來激活使用兔跌。默認激活的是GL_TEXTURE0,所以我們之前的操作都是針對GL_TEXTURE0的峡蟋。

讓我們來激活另一個紋理單元并且對它進行一些操作坟桅。

首先,我們用glActiveTexture(GL_TEXTURE1)來激活紋理單元1层亿,使之可操作桦卒。

然后,將一個新的紋理ID綁定到這個紋理對象上匿又,我們不妨將這個新ID定義成texture2方灾,調(diào)用glBindTexture(GL_TEXTURE_2D,texture2)進行綁定。

接下來碌更,如同之前一樣裕偿,設(shè)置好環(huán)繞和過濾方式。

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

再接著痛单,我們把圖片加載進去嘿棘,綁定到當(dāng)前的紋理單元上:

//加載圖片
stbi_set_flip_vertically_on_load(true);
unsigned char* data2 = stbi_load("awesomeface.png", &width, &height, &nrChannels, 0);
if (data2) {
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data2);
    glGenerateMipmap(GL_TEXTURE_2D);
}
else
    std::cout << "無法加載問題,請檢查代碼或資源是否有誤旭绒。" << std::endl;
stbi_image_free(data2);

最后鸟妙,非常重要的一個步驟是,我們需要告訴OpenGL著色器采樣器和紋理單元之間的對應(yīng)關(guān)系挥吵。

//告訴OpenGL哪個采樣器屬于哪個紋理單元
shader.use();  //著色器要使用之后才能操作
shader.setInt("texture1", 0);  //采樣器1對應(yīng)編號0的紋理單元
shader.setInt("texture2", 1);  //采樣器2對應(yīng)編號1的紋理單元

我們的片元著色器中重父,也需要做相應(yīng)的改動:

uniform sampler2D texture1;
uniform sampler2D texture2;

void main()
{
    FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2);

}

mix函數(shù)是對某個點的紋理進行混合運算,0.2表示該點的顏色20%來自采樣器2,80%來自采樣器1忽匈。好了房午,編譯運行我們的程序。

混合效果

效果很贊丹允,但是還沒達到我們想要的狀態(tài)郭厌。別忘了袋倔,我們還要通過融合因子對其進行控制!

2.2 融合因子控制

直覺上的折柠,我們需要三步走:

  • 第一步:定義一個全局的融合因子
  • 第二步:點擊上下箭頭的時候設(shè)置這個值
  • 第三步:設(shè)置這個融合因子變量值
第一步:定義一個全局的融合因子
float factor = 0.2f;
第二步:點擊上下箭頭的時候設(shè)置這個值

查找上箭頭和下箭頭的按鈕值:GLFW_KEY_UP和GLFW_KEY_DOWN宾娜,在處理輸入的函數(shù)(processInput)中,添加對其的處理扇售。每次按向上箭頭時融合因子增加0.01(最大為1.0)碳默,每次按向下箭頭時融合因子減少0.01,(最小為0.0)。

if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) {
    factor += 0.01f;
    if (factor > 1.0f)
        factor = 1.0f;
}

if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS) {
    factor -= 0.01f;
    if (factor < 0.0f)
        factor = 0.0f;
}
第三步:設(shè)置這個融合因子變量值

在使用了著色器之后缘眶,設(shè)置其值嘱根。

shader.setFloat("factor", factor);

好了,非常簡單巷懈,但是一定要自己實現(xiàn)才行该抒。編譯運行,這下我們可以通過按鈕來控制了6パ唷(沒法放視頻凑保,就不截圖了。)

整個工程的源碼可以在這里找到:http://pan.baidu.com/s/1eRWj7kY

下一篇
目錄
上一篇

參考資料:
www.learningopengl.com(非常好的網(wǎng)站涌攻,建議學(xué)習(xí))

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末欧引,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子恳谎,更是在濱河造成了極大的恐慌芝此,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件因痛,死亡現(xiàn)場離奇詭異婚苹,居然都是意外死亡,警方通過查閱死者的電腦和手機鸵膏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門膊升,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人谭企,你說我怎么就攤上這事廓译。” “怎么了债查?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵非区,是天一觀的道長。 經(jīng)常有香客問我攀操,道長院仿,這世上最難降的妖魔是什么秸抚? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任速和,我火速辦了婚禮歹垫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘颠放。我一直安慰自己排惨,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布碰凶。 她就那樣靜靜地躺著暮芭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪欲低。 梳的紋絲不亂的頭發(fā)上辕宏,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天,我揣著相機與錄音砾莱,去河邊找鬼瑞筐。 笑死,一個胖子當(dāng)著我的面吹牛腊瑟,可吹牛的內(nèi)容都是我干的聚假。 我是一名探鬼主播,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼闰非,長吁一口氣:“原來是場噩夢啊……” “哼膘格!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起财松,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤瘪贱,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后辆毡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體政敢,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年胚迫,在試婚紗的時候發(fā)現(xiàn)自己被綠了喷户。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡访锻,死狀恐怖褪尝,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情期犬,我是刑警寧澤河哑,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站龟虎,受9級特大地震影響璃谨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一佳吞、第九天 我趴在偏房一處隱蔽的房頂上張望拱雏。 院中可真熱鬧,春花似錦底扳、人聲如沸铸抑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鹊汛。三九已至,卻和暖如春阱冶,著一層夾襖步出監(jiān)牢的瞬間刁憋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工木蹬, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留职祷,地道東北人。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓届囚,卻偏偏與公主長得像有梆,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子意系,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內(nèi)容