OpenGL遊戲引擎開發[4]-在OpenGL繪製紋理

上一節我們學會了使用OpenGL着色器,但是在片段着色器中,我們使用簡單純色來繪製物體,這一節,我們要在片段着色器中使用採用器對紋理進行採樣輸出,作爲物體表面的顏色,進而繪製帶有紋理貼圖的物體。

紋理

紋理簡單來說就是一張圖片,最常見的就是王者榮耀中英雄的皮膚,當然,這裏只說遊戲角色的外觀,因爲不同的皮膚還有不同的特效,甚至有不同的人物動作。不同的遊戲人物外觀就是換了不同紋理貼圖。

根據紋理的作用,紋理貼圖可以分爲:普通紋理(就是着色用的)、法線貼圖、切線切圖… 顧名思義,普通紋理中存儲的就是顏色值,就是我們常看的普通圖像;法線貼圖中每個像素存儲的是法線的值,切線貼圖每個像素存的是切線… 後兩種屬於 奇技淫巧,它們自由它們的用途。我們這節主要講如何在OpenGL中使用普通的紋理貼圖,其他的都使用起來都差不多,只不過用途不同罷了。

紋理座標

紋理座標就是用來確定紋理中每個像素的位置的,它的座標範圍是[0,1],這是一個比例值,也就說,任何大小的紋理貼圖的紋理座標都是這個範圍。那麼有人問,那麼超過這個範圍怎麼辦?物體的顏色怎麼賦值呢?不同大小的物體,我們使用同一個紋理,表現效果相同嗎?… 彆着急,我們馬上就要說了。

先來看個例子,我們怎麼把左邊這個圖,貼到右邊的矩形上。其實很簡單,就是繪製頂點的時候,不僅傳遞頂點的位置,還要傳遞定該頂點對對應的紋理座標,要不然前面說,紋理座標也是頂點的一個屬性呢?這樣我們在着色器中,根據頂點的紋理座標去紋理中採樣,獲得紋理的顏色,輸出爲頂點的顏色,這樣,頂點不就像“穿了衣服”一樣了嗎?而不是我們前面設置的純色。

有的書上說,紋理座標的原點在圖像的左上角,有的書上說,紋理座標的原點在圖像的左下角。這。。。你們爲這個問題困擾過嗎?

我從來不擔心這個問題,愛誰誰,反正不是在左上角就是在左下角。我就始終認爲他是左上角,你畫出來看看,發現不對了。你改成左下角不就行了?這裏個座標系之間的轉換很難嗎?不就是y軸座標變成1-y,x軸座標不變的區別嗎?當然紋理座標叫uv座標,不叫xy。我叫習慣了,你們知道就好。

這樣,只要頂點位置和紋理座標對應起來,則紋理採樣器纔會正確採樣紋理的顏色。

紋理參數:紋理環繞方式

紋理參數是OpenGL用來設置如何使用紋理的。比如說,紋理座標範圍是[0,1],如果,程序員給一個頂點的紋理座標設置爲(2,2)這樣的座標,咋辦?這個頂點的顏色該何去何從?

這個問題OpenGL給出了一個叫 紋理環繞方式 的參數。這個參數可以設置很多值:GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_WRAP_TO_BORDER. 不同參數的區別大家自行查閱相關資料。我們這裏講2個最簡單的。

GL_CLAMP: 對於超過 [0,1]範圍的紋理座標直接丟棄,也就說該點的顏色就是 OpenGL 給的默認值,好像是黑色。

GL_REPEAT: 顧名思義,就是重複之前的紋理,那麼(2,2)這個紋理座標對應的頂點顏色就是(1,1)這個紋理座標對應的頂點顏色。其他情況以此類推。

紋理參數:Mipmap

大家都知道,我們現實生活中看到的物體是遠小近大的。遠處的物體你幾乎看不到物體的外觀,而近處的物體你是可以看到的。同樣在OpenGL中,如果使用透視投影的話,那麼物體也會像人觀察物體那樣,近處大,遠處小。但是它不像人眼那麼聰明呀,人眼可以自動調節焦距,遠處的人長啥樣穿什麼衣服,你看不清就不看了唄(睜大眼拼命看的人不在考慮之列),何必浪費能量呢。但是計算機不行呀,它不是人呀,它是機器。你得告訴它,遠處的物體,你就不要給它穿那麼好看的衣服了,因爲我們看不清呀。

來張圖感受下,遠處的頂點和近處的頂點對同一張紋理進行採樣,所以遠處和近處顯示的效果一樣。但是,但是由於 近大遠小 的透視效果,遠處的物體看起來並不是很”精細“,反而有種”過度飽和“的感覺。這就是典型的”吃力不討好“,不但運行渲染性能,還顯示不出好效果。

那麼怎麼辦呢?OpenGL設計了一個叫 Mipmap 的機制,就是在加載紋理的時候,一次性生成很多張大小不同的問題。對於近處的頂點,我們採樣大的紋理,這樣近處的頂點紋理就比較清晰,對於遠處的頂點我們採樣小的紋理,因爲遠處的頂點我們不需要看清楚,這樣既節約了性能,從某種程度上還提高了視覺效果,豈不美哉。計算機科學真的凝聚了人類無限的智慧結晶!!!

再來張圖感受下,這就是使用Mipmap的效果。

我們再來考慮一個問題,你說頂點顯示遠近,多遠纔算遠?多近纔算近?

到底是聰明人呀。 OpenGL中爲mipmap劃分了等級,OpenGL根據紋理的應用環境,自動爲頂點決定使用哪個等級的紋理。不同等級紋理之間需要插值,不同的插值方法性能不同(當然效果好的方法就耗費更多的處理性能),我們只要手動設置這些參數,剩下的OpenGL幫我們自動搞定。

紋理採樣

OpenGL通過在片段着色器聲明一個紋理採樣器,然後根據 頂點着色器傳遞過來的頂點對應的紋理座標進行紋理採樣,將採樣的顏色直接作爲頂點的輸出顏色。其實,頂點光照的處理一般也是在這裏完成的,有時候我們爲了體現物體本來的顏色,還可以將物體顏色和紋理的顏色進行混合。這樣,有紋理,有光照,有物體本身的顏色,通過不同的組合可以生成物體不同的外觀。這就是常說的物體的 材質。 unity中已經把它高度包裝得很好用了,其底層實現就是像這裏這樣對頂點着色。當然,我們這裏只簡單賦值了紋理的顏色,後面學了光照,會做出更加酷炫的效果。

加載並使用紋理

接着我們加載紋理:

在使用紋理之前,我們需要告知OpenGL我們需要使用哪個紋理,因爲同一個程序中可能加載了多個紋理。

然後,你應該可以看到這樣:

同理,帶紋理的球體也是這麼繪製的。

ok。本節結束。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章