OpenGL ES---紋理

紋理是什么

?紋理(TEXTURE),即物體表面的樣子嫩挤。在計算機(jī)的世界中害幅,我們能夠繪制的僅僅是一些非常基礎(chǔ)的形狀岂昭,比如點以现、線、三角形约啊,這些基礎(chǔ)顯然是無法將一個現(xiàn)實世界中的物體很好的描述在屏幕上的邑遏。通常我們通過紋理映射將物體表面圖片貼到物體的幾何圖形上面,完成貼圖的過程恰矩,將物體從現(xiàn)實世界中模擬到虛擬世界中记盒。
?紋理的基礎(chǔ)單元是紋素(Texel,即texture element或texture pixel的合成字)外傅,亦如屏幕的基礎(chǔ)單元是像素纪吮。屏幕上有自己的坐標(biāo)系俩檬,紋理也有,即紋理坐標(biāo)碾盟,一個維度稱為 s棚辽,另一個維度稱為 t,其范圍都在 [0,1]之間巷疼。紋理坐標(biāo)上晚胡,是紋素。

紋理坐標(biāo)

?如上圖所示嚼沿,在 OpenGL的二維世界中估盘,本質(zhì)上,紋理就是一個二維數(shù)組(圖像數(shù)據(jù))骡尽,而紋素就是這個二維數(shù)組中的值遣妥。

紋理映射到屏幕

?接下來,首先我們討論下圖像數(shù)據(jù)是如何從紋理坐標(biāo)下被投射到屏幕上的攀细。

坐標(biāo)映射

?上面我們就講過紋理坐標(biāo)系箫踩。兩個維度,范圍都在[0,1]之間谭贪。無論是使用純色渲染境钟,還是圖片渲染,實際上都是在進(jìn)行顏色渲染俭识,最終慨削,都需要將那塊顏色映射到歸一化坐標(biāo)系中。而歸一化坐標(biāo)系中兩個維度都是在[-1,1]之間套媚。
?由于這種坐標(biāo)系的不一致缚态,就需要將紋理坐標(biāo)系中的圖片映射到歸一化坐標(biāo)系中。這里堤瘤,首先我們會遇到兩個問題:

  • 將紋理坐標(biāo)系中的哪個區(qū)域塊取出來進(jìn)行映射玫芦。
  • 取出來的區(qū)域塊又該如何如何對應(yīng)到歸一化坐標(biāo)系中通過頂點定義的外形中。


    紋理坐標(biāo)和歸一化坐標(biāo)的對應(yīng)關(guān)系

?如上圖所示本辐,我們可以得到以下幾點:

  • 要選取圖片中的哪個區(qū)域是由我們通過紋理頂點坐標(biāo)定義的桥帆。上圖中,我們通過定義(0,0),(0,1),(1,1),(1,0)慎皱,實際上選取了整個圖片部分作為貼片环葵。
  • 要進(jìn)行貼圖的部分定義好了,它所要貼到的地方宝冕,實際上和我們定義的頂點坐標(biāo)按照定義順序一一對應(yīng)(映射)。即邓萨,我們定義的第一個紋理頂點坐標(biāo)地梨,對應(yīng)我們定義的第一個頂點坐標(biāo)菊卷。

?最終,我們可以得到:

屏幕上顯示的圖形

?為了明顯起見宝剖,這里再給出一張圖(改變頂點定義的順序):

改變映射順序后的結(jié)果
紋理過濾(Texture Filtering)

?紋理坐標(biāo)和歸一化坐標(biāo)通常并不能實現(xiàn)一比一的映射關(guān)系洁闰,紋理可能會比歸一化坐標(biāo)系中的幾何圖形大,也可能更小万细。這樣就帶來了這樣的問題:在不能實現(xiàn)一比一映射的時候扑眉,該如何在紋理坐標(biāo)中采樣顯示到歸一化坐標(biāo)中。這就是紋理過濾赖钞,實際上是在處理放大和縮小紋理的操作腰素。
?常見的過濾方式有兩種:最鄰近過濾和雙線性過濾。
?對于最鄰近過濾雪营,顧名思義弓千,是為每個片段選擇最近的紋素;而雙線性過濾献起,使用雙線性插值平滑像素之間的過濾洋访。如下圖所示,顯然線性過濾會有更好的效果谴餐,但是也會消耗更多的計算能力:

最鄰近過濾和雙線性過濾

?我們可以看到姻政,對于雙線性過濾這種方式,特別是在進(jìn)行縮小采樣的時候岂嗓,當(dāng)縮小比例過大汁展,會丟掉很多的細(xì)節(jié),因為不管這個比例如何摄闸,它只會選取周圍的四個點(即四個紋理元素)善镰。為了解決這樣的問題,可以使用 MIP 貼圖的方式解決年枕。關(guān)于 MIP 更多信息可以參考這里

紋理環(huán)繞(Texture Wrapping)

?上面坐標(biāo)中炫欺,我們指定的紋理坐標(biāo)范圍均是在 [0,1]之間,但是如果超出了這個范圍熏兄, 此時刻品洛,我們選擇的紋理區(qū)域大于了實際圖片大小,紋理區(qū)域空白部分該如何處理摩桶,就是紋理環(huán)繞問題桥状。下圖參考

紋理環(huán)繞模式

?綜上,我們了解了紋理坐標(biāo)及其映射硝清。下面辅斟,我們可以進(jìn)行實際地編碼工作了。

在程序中使用紋理

?通常芦拿,我們在程序中使用紋理的步驟是這樣的:

  1. 定義頂點以及渲染程序士飒。其中查邢,在 glsl 程序中使用的 attribute 、uniform酵幕、varying 區(qū)別可參考
    private static final String VERTEX_SHADER =
            "uniform mat4 uMVPMatrix;" +
                    "attribute vec4 vPosition;" +
                    "attribute vec2 a_texCoord;" +
                    "varying vec2 v_texCoord;" +
                    "void main() {" +
                    " gl_Position = uMVPMatrix * vPosition;" +
                    " v_texCoord = a_texCoord;" +
                    "}";
    private static final String FRAGMENT_SHADER =
            "precision mediump float;" +
                    "varying vec2 v_texCoord;" +
                    "uniform sampler2D s_texture;" +
                    "void main() {" +
                    " gl_FragColor = texture2D(s_texture, v_texCoord);" +
                    "}";

private static final float[] TEX_VERTEX = {   // in clockwise order:
            0, 1f,  // top left
            1f, 0,  // bottom right
            0, 0,  // bottom left
    };

private static final float[] VERTEX = {   // in counterclockwise order:
            -1, -1f, 0, // bottom left
            1, 1, 0,   // top right
            -1, 1, 0,  // top left
    };
  1. 加載圖片扰藕,創(chuàng)建 texture 紋理,然后將圖片指定在紋理上芳撒。
GLES20.glGenTextures(1, texNames, 0);
mTexName = texNames[0];
Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(),
                R.drawable.cat);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTexName);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
  1. 指定紋理參數(shù)邓深,主要包括紋理過濾和紋理環(huán)繞方式。
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
                GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
                GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
                GLES20.GL_MIRRORED_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
                GLES20.GL_MIRRORED_REPEAT);
  1. 為幾何頂點指定相應(yīng)的紋理坐標(biāo)中的頂點
mTexCoordHandle = GLES20.glGetAttribLocation(mProgram, "a_texCoord");
GLES20.glEnableVertexAttribArray(mTexCoordHandle);
GLES20.glVertexAttribPointer(mTexCoordHandle, 2, GLES20.GL_FLOAT, false, 0,
                mTexVertexBuffer);
  1. 繪制
 GLES20.glDrawArrays(GLES20.GL_TRIANGLES,0,3);

?完整代碼MyRender.java
?需要注意的一點笔刹,上述代碼中我們定義的順序芥备。實際上,在計算機(jī)中圖片都是原點在左上角徘熔,x軸向右延伸门躯,y軸向下延伸,如下圖所示酷师。

小結(jié)

?本節(jié)中讶凉,我們對 OpenGL 中的紋理進(jìn)行了解和應(yīng)用。在現(xiàn)實世界中物體有太多的細(xì)節(jié)山孔,紋理給我們提供了一種方式將這些細(xì)節(jié)通過圖片的方式貼在屏幕上的幾何物體上懂讯。這對于二維平面來說,從效果上來說可能不具有太多吸引力台颠,因為我們的圖片本來就是二維的褐望,但是 OpenGL 也能對其進(jìn)行一些變換(剪切、翻轉(zhuǎn)串前、平移等等)瘫里,而且這些變換是運行在 GPU 上。下面荡碾,我們將進(jìn)入三維的世界谨读。

參考鏈接
Texture Mapping
Texture Mapping
OPENGL ES 2.0:紋理
Mipmap
Textures objects and parameters

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市坛吁,隨后出現(xiàn)的幾起案子劳殖,更是在濱河造成了極大的恐慌,老刑警劉巖拨脉,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哆姻,死亡現(xiàn)場離奇詭異,居然都是意外死亡玫膀,警方通過查閱死者的電腦和手機(jī)矛缨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人劳景,你說我怎么就攤上這事誉简。” “怎么了盟广?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長瓮钥。 經(jīng)常有香客問我筋量,道長,這世上最難降的妖魔是什么碉熄? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任桨武,我火速辦了婚禮,結(jié)果婚禮上锈津,老公的妹妹穿的比我還像新娘呀酸。我一直安慰自己,他們只是感情好琼梆,可當(dāng)我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布性誉。 她就那樣靜靜地躺著,像睡著了一般茎杂。 火紅的嫁衣襯著肌膚如雪错览。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天煌往,我揣著相機(jī)與錄音倾哺,去河邊找鬼。 笑死刽脖,一個胖子當(dāng)著我的面吹牛羞海,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播曲管,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼却邓,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了翘地?” 一聲冷哼從身側(cè)響起申尤,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎衙耕,沒想到半個月后昧穿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡橙喘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年时鸵,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡饰潜,死狀恐怖初坠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情彭雾,我是刑警寧澤碟刺,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站薯酝,受9級特大地震影響半沽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜吴菠,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一者填、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧做葵,春花似錦占哟、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至棠涮,卻和暖如春谬哀,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背严肪。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工史煎, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人驳糯。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓篇梭,卻偏偏與公主長得像,于是被迫代替她去往敵國和親酝枢。 傳聞我的和親對象是個殘疾皇子恬偷,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,792評論 2 345

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

  • 前言 本文是關(guān)于OpenGL ES的系統(tǒng)性學(xué)習(xí)過程,記錄了自己在學(xué)習(xí)OpenGL ES時的收獲帘睦。這篇文章的目標(biāo)是學(xué)...
    秦明Qinmin閱讀 10,391評論 7 22
  • 1袍患,紋理【1】什么是紋理:定義:在計算機(jī)圖形學(xué)中,紋理既包括通常意義上物體表面的紋理竣付。也就是我們土話所講的使物體表...
    simple_0955閱讀 631評論 0 1
  • 1 紋理基礎(chǔ) 紋理是一種結(jié)構(gòu)化的存儲形式(Textures are a structured form of st...
    RichardJieChen閱讀 15,674評論 0 9
  • 概述:紋理是一個用來保存圖像的顏色元素值的OpenGL ES緩存诡延。當(dāng)把紋理應(yīng)用到幾何圖形中后,會使渲染的場景顯得更...
    HoFie閱讀 928評論 0 1
  • 版本記錄 前言 OpenGL 圖形庫項目中一直也沒用過古胆,最近也想學(xué)著使用這個圖形庫肆良,感覺還是很有意思筛璧,也就自然想著...
    刀客傳奇閱讀 8,785評論 0 8