欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Opengl?ES之紋理貼圖使用示例

 更新時(shí)間:2022年09月29日 11:51:02   作者:思想覺悟  
這篇文章主要為大家介紹了Opengl?ES之紋理貼圖使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

正文

紋理可以理解為一個(gè)二維數(shù)組,它可以存儲(chǔ)大量的數(shù)據(jù),這些數(shù)據(jù)可以發(fā)送到著色器上。一般情況下我們所說的紋理是表示一副2D圖,此時(shí)紋理存儲(chǔ)的數(shù)據(jù)就是這個(gè)圖的像素?cái)?shù)據(jù)。

所謂的紋理貼圖,就是使用Opengl將這個(gè)紋理數(shù)據(jù)渲染出來,這個(gè)過程有點(diǎn)像裝修工人給墻體貼瓷磚,而瓷磚好比作紋理。

紋理坐標(biāo)

如果為了將一副紋理圖貼到Opengl繪制的一個(gè)矩形上,那么就需要解決一個(gè)問題,如何知道矩形的具體某個(gè)點(diǎn)對(duì)應(yīng)紋理圖的某個(gè)點(diǎn)呢?為了解決這個(gè)問題就引出了紋理坐標(biāo), 通過矩形的頂點(diǎn)坐標(biāo)與紋理坐標(biāo)關(guān)聯(lián),這樣就明確了每個(gè)頂點(diǎn)應(yīng)該顯示紋理圖的那部分像素?cái)?shù)據(jù)。

紋理坐標(biāo)在x和y軸上,范圍為0到1之間。使用紋理坐標(biāo)獲取紋理顏色叫做采樣(Sampling)。紋理坐標(biāo)起始于(0, 0),也就是紋理圖片的左下角,終始于(1, 1),即紋理圖片的右上角,如下圖所示:

紋理環(huán)繞

紋理坐標(biāo)的值介于0到1之間,如果我們把紋理坐標(biāo)設(shè)置成大于1那么會(huì)發(fā)生什么呢?OpenGL默認(rèn)的行為是重復(fù)這個(gè)紋理圖像,那么利用這個(gè)默認(rèn)的特性我們能做些什么呢?那么比較火的抖音四分屏、九分屏濾鏡不就是可以用這個(gè)特性巧妙地實(shí)現(xiàn)嗎。

以下是通過改變紋理坐標(biāo)實(shí)現(xiàn)四分屏和九分屏的一個(gè)小技巧:

//?4分屏
const?static?GLfloat?TEXTURE_COORD[]?=?{
????????2.0f,2.0f,?//?右下
????????2.0f,0.0f,?//?右上
????????0.0f,2.0f,?//?左下
????????0.0f,0.0f?//?左上
};
//?九分屏
const?static?GLfloat?TEXTURE_COORD[]?=?{
????????3.0f,3.0f,?//?右下
????????3.0f,0.0f,?//?右上
????????0.0f,3.0f,?//?左下
????????0.0f,0.0f?//?左上
};

當(dāng)然,當(dāng)紋理坐標(biāo)超過1這個(gè)范圍時(shí),Opengl也提供了其他的選擇,例如:

GL_REPEAT?//?對(duì)紋理的默認(rèn)行為。重復(fù)紋理圖像。
GL_MIRRORED_REPEAT?//和GL_REPEAT一樣,但每次重復(fù)圖片是鏡像放置的。
GL_CLAMP_TO_EDGE?//紋理坐標(biāo)會(huì)被約束在0到1之間,超出的部分會(huì)重復(fù)紋理坐標(biāo)的邊緣,產(chǎn)生一種邊緣被拉伸的效果。
GL_CLAMP_TO_BORDER?//超出的坐標(biāo)為用戶指定的邊緣顏色。

紋理環(huán)繞效果圖

以上特性可以通過函數(shù)glTexParameteri設(shè)置:

glTexParameteri(GL_TEXTURE_2D,?GL_TEXTURE_WRAP_S,?GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D,?GL_TEXTURE_WRAP_T,?GL_MIRRORED_REPEAT);

紋理過濾

紋理過濾實(shí)際就是紋理在放大縮小的過程中像素的處理方式。其中在Opengl ES常用的兩種紋理過濾方式是GL_NEAREST(鄰近過濾)和GL_LINEAR(也叫線性過濾)。

  • GL_NEAREST是OpenGL默認(rèn)的紋理過濾方式。當(dāng)設(shè)置為GL_NEAREST的時(shí)候,OpenGL會(huì)選擇中心點(diǎn)最接近紋理坐標(biāo)的那個(gè)像素。
  • GL_LINEAR(也叫線性過濾,(Bi)linear Filtering)它會(huì)基于紋理坐標(biāo)附近的紋理像素,計(jì)算出一個(gè)插值,近似出這些紋理像素之間的顏色。一個(gè)紋理像素的中心距離紋理坐標(biāo)越近,那么這個(gè)紋理像素的顏色對(duì)最終的樣本顏色的貢獻(xiàn)越大。

GL_NEAREST產(chǎn)生了顆粒狀的圖案,我們能夠清晰看到組成紋理的像素,而GL_LINEAR能夠產(chǎn)生更平滑的圖案,很難看出單個(gè)的紋理像素。

同理,紋理過濾特性也是通過函數(shù)glTexParameteri設(shè)置:

glTexParameteri(GL_TEXTURE_2D,?GL_TEXTURE_MIN_FILTER,?GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,?GL_TEXTURE_MAG_FILTER,?GL_LINEAR);

紋理單元

紋理單元的主要目的是讓我們在著色器中可以使用多于一個(gè)的紋理。通過把紋理單元賦值給采樣器,我們可以一次綁定多個(gè)紋理,只要我們首先激活對(duì)應(yīng)的紋理單元。 例如使用Opengl ES對(duì)視頻解碼后的YUV進(jìn)行渲染就需要用到紋理單元的相關(guān)知識(shí)點(diǎn)。

Opengl中紋理的使用

在Opengl中使用紋理主要有以下幾個(gè)步驟:

  • 創(chuàng)建紋理glGenTextures
  • 激活紋理glActiveTexture
  • 綁定紋理glBindTexture,傳遞特定的紋理id進(jìn)行綁定
  • 上傳紋理數(shù)據(jù)glTexImage2D
  • 解除紋理綁定,glBindTexture,傳遞0進(jìn)行解除綁定

紋理坐標(biāo)映射關(guān)系

在了解紋理貼圖之前我們先回顧一下三個(gè)坐標(biāo)系統(tǒng),分別是紋理坐標(biāo)系統(tǒng)、手機(jī)屏幕坐標(biāo)系統(tǒng)、Opengl坐標(biāo)系統(tǒng)。這三個(gè)坐標(biāo)系統(tǒng)的的原點(diǎn)各不相同,紋理坐標(biāo)系統(tǒng)我們上面已經(jīng)介紹過了,這里不再重復(fù)。而手機(jī)屏幕坐標(biāo)系統(tǒng)則是原點(diǎn)位于左上角,X軸向右為正,Y軸向下為正的坐標(biāo)系統(tǒng)。 而Opengl坐標(biāo)系統(tǒng)則是原點(diǎn)位于中心,X軸向右為正,Y軸向下為正,其值介于-1到1之間的一套坐標(biāo)系統(tǒng)。

既然紋理貼圖就像裝修工人貼瓷磚一樣,那么直接將紋理坐標(biāo)和Opengl的頂點(diǎn)坐標(biāo)一一對(duì)應(yīng)起來即可,也就是如下圖:

我們按照這個(gè)映射關(guān)系建立貼圖:

//?頂點(diǎn)坐標(biāo),使用繪制兩個(gè)三角形組成一個(gè)矩形的形式(三角形帶)
//?第一第二第三個(gè)點(diǎn)組成一個(gè)三角形,第二第三第四個(gè)點(diǎn)組成一個(gè)三角形
const?static?GLfloat?VERTICES[]?=?{
????????0.5f,-0.5f,?//?右下
????????0.5f,0.5f,?//?右上
????????-0.5f,-0.5f,?//?左下
????????-0.5f,0.5f?//?左上
};
//?紋理坐標(biāo)(原點(diǎn)在左下角,這樣貼圖看到的會(huì)是倒置的
const?static?GLfloat?TEXTURE_COORD[]?=?{
????????1.0f,0.0f,?//?右下
????????1.0f,1.0f,?//?右上
????????0.0f,0.0f,?//?左下
????????0.0f,1.0f?//?左上
};

運(yùn)行發(fā)現(xiàn)圖是貼上去了,但是看到的貼圖卻是倒置的,如下:

這是為什么呢?

因?yàn)榧y理的生成是由圖片像素來生成的,而圖像的存儲(chǔ)是從左上角開始的,但是紋理坐標(biāo)原點(diǎn)卻是在左下角的(筆者也不知道為什么要這么奇葩),所以就產(chǎn)生了倒置現(xiàn)象,因此正確的映射關(guān)系應(yīng)該是以圖片的左上角為原點(diǎn)做映射才對(duì),而這也剛好與手機(jī)屏幕坐標(biāo)系統(tǒng)匹配。

也就說正確的映射關(guān)系是需要先將以左下角為原點(diǎn)的紋理坐標(biāo)進(jìn)行倒置,然后再建立映射關(guān)系,這也是為什么有些博客說紋理坐標(biāo)的原點(diǎn)是在左上角的原因(其實(shí)這是不對(duì)的,紋理坐標(biāo)就是在圖片的左下角,說在左上角的就是一個(gè)技巧),那么紋理坐標(biāo)倒置后再映射如圖: !

廢話少說,放碼過來...

#include?"TextureMapOpengl.h"
#include?"../utils/Log.h"
//?頂點(diǎn)著色器
static?const?char?*ver?=?"#version?300?es\n"
?????????????????????????"in?vec4?aPosition;\n"
?????????????????????????"in?vec2?aTexCoord;\n"
?????????????????????????"out?vec2?TexCoord;\n"
?????????????????????????"void?main()?{\n"
?????????????????????????"??TexCoord?=?aTexCoord;\n"
?????????????????????????"??gl_Position?=?aPosition;\n"
?????????????????????????"}";
//?片元著色器
static?const?char?*fragment?=?"#version?300?es\n"
??????????????????????????????"precision?mediump?float;\n"
??????????????????????????????"out?vec4?FragColor;\n"
??????????????????????????????"in?vec2?TexCoord;\n"
??????????????????????????????"uniform?sampler2D?ourTexture;\n"
??????????????????????????????"void?main()\n"
??????????????????????????????"{\n"
??????????????????????????????"????FragColor?=?texture(ourTexture,?TexCoord);\n"
??????????????????????????????"}";
//?使用繪制兩個(gè)三角形組成一個(gè)矩形的形式(三角形帶)
//?第一第二第三個(gè)點(diǎn)組成一個(gè)三角形,第二第三第四個(gè)點(diǎn)組成一個(gè)三角形
const?static?GLfloat?VERTICES[]?=?{
????????0.5f,-0.5f,?//?右下
????????0.5f,0.5f,?//?右上
????????-0.5f,-0.5f,?//?左下
????????-0.5f,0.5f?//?左上
};
//?紋理坐標(biāo)(原點(diǎn)在左下角,這樣貼圖看到的會(huì)是倒置的
//const?static?GLfloat?TEXTURE_COORD[]?=?{
//????????1.0f,0.0f,?//?右下
//????????1.0f,1.0f,?//?右上
//????????0.0f,0.0f,?//?左下
//????????0.0f,1.0f?//?左上
//};
//?貼圖紋理坐標(biāo)(參考手機(jī)屏幕坐標(biāo)系統(tǒng),原點(diǎn)在左上角)
//由于對(duì)一個(gè)OpenGL紋理來說,它沒有內(nèi)在的方向性,因此我們可以使用不同的坐標(biāo)把它定向到任何我們喜歡的方向上,然而大多數(shù)計(jì)算機(jī)圖像都有一個(gè)默認(rèn)的方向,它們通常被規(guī)定為y軸向下,X軸向右
const?static?GLfloat?TEXTURE_COORD[]?=?{
????????1.0f,1.0f,?//?右下
????????1.0f,0.0f,?//?右上
????????0.0f,1.0f,?//?左下
????????0.0f,0.0f?//?左上
};
//?四分屏??GL_REPEAT環(huán)繞方式
//const?static?GLfloat?TEXTURE_COORD[]?=?{
//????????2.0f,2.0f,?//?右下
//????????2.0f,0.0f,?//?右上
//????????0.0f,2.0f,?//?左下
//????????0.0f,0.0f?//?左上
//};
//?九分屏?GL_REPEAT環(huán)繞方式
//const?static?GLfloat?TEXTURE_COORD[]?=?{
//????????3.0f,3.0f,?//?右下
//????????3.0f,0.0f,?//?右上
//????????0.0f,3.0f,?//?左下
//????????0.0f,0.0f?//?左上
//};
TextureMapOpengl::TextureMapOpengl():BaseOpengl()?{
????initGlProgram(ver,fragment);
????positionHandle?=?glGetAttribLocation(program,"aPosition");
????textureHandle?=?glGetAttribLocation(program,"aTexCoord");
????textureSampler?=?glGetUniformLocation(program,"ourTexture");
????LOGD("program:%d",program);
????LOGD("positionHandle:%d",positionHandle);
????LOGD("textureHandle:%d",textureHandle);
????LOGD("textureSample:%d",textureSampler);
}
void?TextureMapOpengl::setPixel(void?*data,?int?width,?int?height,?int?length)?{
????LOGD("texture?setPixel");
????glGenTextures(1,?&textureId);
????//?激活紋理,注意以下這個(gè)兩句是搭配的,glActiveTexture激活的是那個(gè)紋理,就設(shè)置的sampler2D是那個(gè)
????//?默認(rèn)是0,如果不是0的話,需要在onDraw的時(shí)候重新激活一下?
//????glActiveTexture(GL_TEXTURE0);
//????glUniform1i(textureSampler,?0);
//?例如,一樣的
????glActiveTexture(GL_TEXTURE2);
????glUniform1i(textureSampler,?2);
????//?綁定紋理
????glBindTexture(GL_TEXTURE_2D,?textureId);
????//?為當(dāng)前綁定的紋理對(duì)象設(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);
????glTexParameteri(GL_TEXTURE_2D,?GL_TEXTURE_MAG_FILTER,?GL_LINEAR);
????glTexImage2D(GL_TEXTURE_2D,?0,?GL_RGBA,?width,?height,?0,?GL_RGBA,?GL_UNSIGNED_BYTE,?data);
????//?生成mip貼圖
????glGenerateMipmap(GL_TEXTURE_2D);
????glBindTexture(GL_TEXTURE_2D,?textureId);
????//?解綁定
????glBindTexture(GL_TEXTURE_2D,?0);
}
void?TextureMapOpengl::onDraw()?{
????glClearColor(0.0f,?1.0f,?0.0f,?1.0f);
????glClear(GL_COLOR_BUFFER_BIT);
????glUseProgram(program);
????//?激活紋理
????glActiveTexture(GL_TEXTURE2);
????glUniform1i(textureSampler,?2);
????//?綁定紋理
????glBindTexture(GL_TEXTURE_2D,?textureId);
????/**
?????*?size?幾個(gè)數(shù)字表示一個(gè)點(diǎn),顯示是兩個(gè)數(shù)字表示一個(gè)點(diǎn)
?????*?normalized?是否需要?dú)w一化,不用,這里已經(jīng)歸一化了
?????*?stride?步長,連續(xù)頂點(diǎn)之間的間隔,如果頂點(diǎn)直接是連續(xù)的,也可填0
?????*/
????//?啟用頂點(diǎn)數(shù)據(jù)
????glEnableVertexAttribArray(positionHandle);
????glVertexAttribPointer(positionHandle,2,GL_FLOAT,GL_FALSE,0,VERTICES);
????//?紋理坐標(biāo)
????glEnableVertexAttribArray(textureHandle);
????glVertexAttribPointer(textureHandle,2,GL_FLOAT,GL_FALSE,0,TEXTURE_COORD);
????//?4個(gè)頂點(diǎn)繪制兩個(gè)三角形組成矩形
?????glDrawArrays(GL_TRIANGLE_STRIP,0,4);
????glUseProgram(0);
????//?禁用頂點(diǎn)
????glDisableVertexAttribArray(positionHandle);
????if(nullptr?!=?eglHelper){
????????eglHelper->swapBuffers();
????}
????glBindTexture(GL_TEXTURE_2D,?0);
}
TextureMapOpengl::~TextureMapOpengl()?{
????LOGD("TextureMapOpengl析構(gòu)函數(shù)");
}

仔細(xì)看注釋多理解...

紋理貼圖運(yùn)行結(jié)果

以上就是Opengl ES之紋理貼圖使用示例的詳細(xì)內(nèi)容,更多關(guān)于Opengl ES 紋理貼圖的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Android ExpandableRecyclerView使用方法詳解

    Android ExpandableRecyclerView使用方法詳解

    這篇文章主要為大家詳細(xì)介紹了Android ExpandableRecyclerView的使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • Android 自定義Livedata使用示例解析

    Android 自定義Livedata使用示例解析

    這篇文章主要為大家介紹了Android 自定義Livedata使用示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • Android Studio添加日志過濾方式

    Android Studio添加日志過濾方式

    這篇文章主要介紹了Android Studio添加日志過濾方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-04-04
  • Android?控件自動(dòng)貼邊實(shí)現(xiàn)實(shí)例詳解

    Android?控件自動(dòng)貼邊實(shí)現(xiàn)實(shí)例詳解

    這篇文章主要為大家介紹了Android?控件自動(dòng)貼邊實(shí)現(xiàn)實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • Android編程中延后處理事件的方法小結(jié)

    Android編程中延后處理事件的方法小結(jié)

    這篇文章主要介紹了Android編程中延后處理事件的方法,總結(jié)分析了Handler和TimerTask相結(jié)合以及使用postDelayed實(shí)現(xiàn)延后處理事件的相關(guān)操作技巧,需要的朋友可以參考下
    2017-03-03
  • Android提高之XML解析與生成實(shí)例詳解

    Android提高之XML解析與生成實(shí)例詳解

    這篇文章主要介紹了Android的XML解析與生成方法,相信對(duì)大家的Android項(xiàng)目開發(fā)有一定的借鑒參考作用,需要的朋友可以參考下
    2014-08-08
  • 詳談Android中Matrix的set、pre、post的區(qū)別

    詳談Android中Matrix的set、pre、post的區(qū)別

    下面小編就為大家?guī)硪黄斦凙ndroid中Matrix的set、pre、post的區(qū)別。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-04-04
  • Android 配置打包簽名信息的兩種方法

    Android 配置打包簽名信息的兩種方法

    這篇文章主要介紹了Android 配置打包簽名信息的兩種方法,非常不錯(cuò),具有一定的參考借鑒加載,需要的朋友可以參考下
    2018-06-06
  • Android的異步任務(wù)AsyncTask詳解

    Android的異步任務(wù)AsyncTask詳解

    本文給大家介紹的是Android的異步任務(wù)AsyncTask,在Android中實(shí)現(xiàn)異步任務(wù)機(jī)制有兩種方式,Handler和AsyncTask。今天我們先來主要談下ASYNCTASK。
    2015-07-07
  • Android 監(jiān)聽Notification 被清除實(shí)例代碼

    Android 監(jiān)聽Notification 被清除實(shí)例代碼

    本文主要介紹Android 監(jiān)聽Notification 事件,這里給大家提供實(shí)例代碼進(jìn)行參考,有需要的小伙伴可以參考下
    2016-07-07

最新評(píng)論