OpenGL Texture

我們基于前面四邊形的例子撵割,給四邊形貼個圖


screenshot-1550647708208.jpg

文理坐標

紋理的坐標是屏幕左下角

{
    0.0f, 0.0f, // 左下角
    1.0f, 0.0f, // 右下角
    1.0f, 1.0f ,// 左上角
    0.0f,1.0f //右上角
}
文理坐標

然后看下文理創(chuàng)建的方法

private fun genTexture(bitmap: Bitmap): Int {
        var textureId = IntArray(1)
        GLES30.glGenTextures(1, textureId, 0)
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureId[0])
        GLUtils.texImage2D(GLES30.GL_TEXTURE_2D, 0, bitmap, 0)
        //過濾方式 GL_LINEAR 線性取插值 GL_NEAREST 取最靠近
        //當圖片縮小時的模式
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST)
        //當圖片放大時的模式
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR)

        //文理橫軸的縮放方式 GL_CLAMP_TO_EDGE:紋理坐標會被約束在0到1之間瓢湃,超出的部分會重復紋理坐標的邊緣,產生一種邊緣被拉伸的效果
        // GL_REPEAT 重復
        // GL_MIRRORED_REPEAT 鏡像重復
        //GL_CLAMP_TO_BORDER 邊緣顏色
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE)
        //文理縱軸的縮放方式
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE)
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0)
        return textureId[0]
    }

要注意文理環(huán)繞方式和紋理過濾方式钙勃,注釋里已經寫清楚了

繪畫時綁定下文理就能畫出來了

override fun onDrawFrame(gl: GL10?) {
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)
        esShader.use()
        GLES30.glBindVertexArray(vao[0])
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, texture)
        GLES30.glDrawElements(
            //圖元的類型
            GLES30.GL_TRIANGLES,
            //定點個數
            6,
            //定點數據類型
            GLES30.GL_UNSIGNED_SHORT,
            //頂點偏移量
            0
        )

    }

還要更換著色器

頂點
#version 300 es
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;
out vec3 ourColor;
out vec2 TexCoord;
void main() {
    gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
    ourColor=aColor;
    TexCoord=aTexCoord;
}
片段
#version 300 es
precision mediump float;
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;

uniform sampler2D ourTexture;
void main()
{
      FragColor = texture(ourTexture, TexCoord);
}

這樣就能顯示出紋理了

學習OpenGL就是為了之后視頻濾鏡打基礎,現在可以嘗試下了
比如給箱子圖片加點顏色


screenshot-1550648668524.jpg

我們改下片段著色器

#version 300 es
precision mediump float;
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;

uniform sampler2D ourTexture;
void main()
{
//      FragColor = texture(ourTexture, TexCoord);
    FragColor = texture(ourTexture, TexCoord)* vec4(ourColor, 1.0);
}

讓箱子的顏色乘以添加的顏色,這樣兩個顏色就混合一塊了

現在才使用一個文理置逻,我們使用兩個文理來做個有趣的事情
兩張圖片,一張作為背景备绽,一張作為人物券坞,讓他們一塊顯示


背景圖
人物圖

不用在于兩個圖片大小不一致,因為小的會放大肺素,大的會放小恨锚,都取決于坐標。


屏幕快照 2019-02-20 下午4.14.46.png

效果就是兩張圖片混合一塊了倍靡,很多濾鏡都是通過這樣做的
要實現這效果的話改下著色器就可以了

頂點

#version 300 es
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;
out vec3 ourColor;
out vec2 TexCoord;
void main() {
    gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
    ourColor=aColor;
    TexCoord=vec2(aTexCoord.x,1.0-aTexCoord.y);
}

TexCoord=vec2(aTexCoord.x,1.0-aTexCoord.y); 這句要注意 不然圖片會翻轉的猴伶,因為文理是左下角 但是圖片是左上角開始的

片段

#version 300 es
precision mediump float;
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;

uniform sampler2D texture1;
uniform sampler2D texture2;

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

就是兩個文理混合,mix是著色器語音的內置函數塌西,如果第三個值是0.0他挎,它會返回第一個輸入;如果是1.0捡需,會返回第二個輸入值办桨。0.2會返回80%的第一個輸入顏色和20%的第二個輸入顏色,即返回兩個紋理的混合色站辉。
看下所有代碼

class MixTextureRender : GLSurfaceView.Renderer {

    private val vao = IntArray(1)
    private val vbo = IntArray(1)
    private val ebo = IntArray(1)
    private var esShader = Shader()
    private var texture1 = 0
    private var texture2 = 0

    private var vertices = floatArrayOf(
        //頂點            //顏色             //文理
        0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,// 右上角
        0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,// 右下角
        -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,// 左下角
        -0.5f, 0.5f, 0.0f, 0.5f, 0.5f, 0.5f, 0.0f, 1.0f// 左上角
    )

    private var indices = shortArrayOf(
        0, 1, 3, // 第一個三角形
        1, 2, 3  // 第二個三角形
    )

    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        GLES30.glClearColor(0.2f, 0.3f, 0.3f, 1.0f)

        //vao
        GLES30.glGenVertexArrays(1, vao, 0)
        GLES30.glBindVertexArray(vao[0])
        //vbo
        GLES30.glGenBuffers(1, vbo, 0)
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbo[0])
        val vertexBuffer = DataUtil.createByteBuffer(vertices)
        //復制數據到opengl
        GLES30.glBufferData(
            //頂點緩沖對象當前綁定到GL_ARRAY_BUFFER目標上
            GLES30.GL_ARRAY_BUFFER,
            //指定傳輸數據的大小(以字節(jié)為單位)
            vertices.size * DataUtil.sizeof(GLES30.GL_FLOAT),
            //發(fā)送的實際數據
            vertexBuffer,
            //GL_STATIC_DRAW :數據不會或幾乎不會改變呢撞。
            //GL_DYNAMIC_DRAW:數據會被改變很多。
            //GL_STREAM_DRAW :數據每次繪制時都會改變
            GLES30.GL_STATIC_DRAW
        )
        //設置頂點數組指針
        GLES30.glVertexAttribPointer(
            //shader中 layout(location = 0)的值
            0,
            //頂點屬性的大小庵寞。頂點屬性是一個vec3狸相,它由3個值組成,所以大小是3
            3,
            //數據的類型
            GLES30.GL_FLOAT,
            //GL_TRUE捐川,數據被標準化脓鹃,所有數據都會被映射到0(對于有符號型signed數據是-1)到1之間。我們把它設置為GL_FALSE
            false,
            //步長古沥,它告訴我們在連續(xù)的頂點屬性組之間的間隔 字節(jié)單位
            8 * DataUtil.sizeof(GLES30.GL_FLOAT),
            //數據偏移量 這里只有頂點 位置數據在數組的開頭瘸右,所以這里是0
            0
        )
        GLES30.glEnableVertexAttribArray(0)

        //設置顏色數組指針
        GLES30.glVertexAttribPointer(
            //shader中 layout(location = 0)的值
            1,
            //頂點屬性的大小。頂點屬性是一個vec3岩齿,它由3個值組成太颤,所以大小是3
            3,
            //數據的類型
            GLES30.GL_FLOAT,
            //GL_TRUE,數據被標準化盹沈,所有數據都會被映射到0(對于有符號型signed數據是-1)到1之間龄章。我們把它設置為GL_FALSE
            false,
            //步長,它告訴我們在連續(xù)的頂點屬性組之間的間隔 字節(jié)單位
            8 * DataUtil.sizeof(GLES30.GL_FLOAT),
            //數據偏移量 編譯前面
            3 * DataUtil.sizeof(GLES30.GL_FLOAT)
        )
        GLES30.glEnableVertexAttribArray(1)


        //設置顏色數組指針
        GLES30.glVertexAttribPointer(
            //shader中 layout(location = 0)的值
            2,
            //頂點屬性的大小。頂點屬性是一個vec3做裙,它由3個值組成岗憋,所以大小是3
            2,
            //數據的類型
            GLES30.GL_FLOAT,
            //GL_TRUE,數據被標準化锚贱,所有數據都會被映射到0(對于有符號型signed數據是-1)到1之間仔戈。我們把它設置為GL_FALSE
            false,
            //步長,它告訴我們在連續(xù)的頂點屬性組之間的間隔 字節(jié)單位
            8 * DataUtil.sizeof(GLES30.GL_FLOAT),
            //數據偏移量 編譯前面
            6 * DataUtil.sizeof(GLES30.GL_FLOAT)
        )
        GLES30.glEnableVertexAttribArray(2)

        //vbo end

        //ebo start
        GLES30.glGenBuffers(1, ebo, 0)
        GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, ebo[0])
        val indexBuffer = DataUtil.createByteBuffer(indices)
        //復制數據到opengl
        GLES30.glBufferData(
            //頂點緩沖對象當前綁定到GL_ELEMENT_ARRAY_BUFFER目標上
            GLES30.GL_ELEMENT_ARRAY_BUFFER,
            //指定傳輸數據的大小(以字節(jié)為單位)
            indices.size * DataUtil.sizeof(GLES30.GL_SHORT),
            //發(fā)送的實際數據
            indexBuffer,
            //GL_STATIC_DRAW :數據不會或幾乎不會改變拧廊。
            //GL_DYNAMIC_DRAW:數據會被改變很多监徘。
            //GL_STREAM_DRAW :數據每次繪制時都會改變
            GLES30.GL_STATIC_DRAW
        )
        //ebo end

        //vao end

        //shader
        esShader.loadProgramFromAsset(MyApp.context, "mix_texture_vert.glsl", "mix_texture_frag.glsl")

        //create texture1
        var bitmap = BitmapFactory.decodeResource(MyApp.context.resources, R.mipmap.test)
        texture1 = genTexture(bitmap)
        //記得用完釋放
        bitmap.recycle()

        bitmap = BitmapFactory.decodeResource(MyApp.context.resources, R.mipmap.face)
        texture2 = genTexture(bitmap)
        //記得用完釋放
        bitmap.recycle()

        esShader.use()
        esShader.setInt("texture1", 0)
        esShader.setInt("texture2", 1)

    }

    private fun genTexture(bitmap: Bitmap): Int {
        var textureId = IntArray(1)
        GLES30.glGenTextures(1, textureId, 0)
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureId[0])
        GLUtils.texImage2D(GLES30.GL_TEXTURE_2D, 0, bitmap, 0)
        //過濾方式 GL_LINEAR 線性取插值 GL_NEAREST 取最靠近
        //當圖片縮小時的模式
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST)
        //當圖片放大時的模式
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR)

        //文理橫軸的縮放方式 GL_CLAMP_TO_EDGE:紋理坐標會被約束在0到1之間,超出的部分會重復紋理坐標的邊緣吧碾,產生一種邊緣被拉伸的效果
        // GL_REPEAT 重復
        // GL_MIRRORED_REPEAT 鏡像重復
        //GL_CLAMP_TO_BORDER 邊緣顏色
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE)
        //文理縱軸的縮放方式
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE)
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0)
        return textureId[0]
    }


    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
        GLES30.glViewport(0, 0, width, height)
    }

    override fun onDrawFrame(gl: GL10?) {
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)
        GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, texture1)
        GLES30.glActiveTexture(GLES30.GL_TEXTURE1)
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, texture2)
        esShader.use()
        GLES30.glBindVertexArray(vao[0])
        GLES30.glDrawElements(
            //圖元的類型
            GLES30.GL_TRIANGLES,
            //定點個數
            6,
            //定點數據類型
            GLES30.GL_UNSIGNED_SHORT,
            //頂點偏移量
            0
        )

    }
}

效果就是這些了

我么還可以合成顏色進去哦


屏幕快照 2019-02-20 下午4.46.44.png
void main()
{
    FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2)* vec4(ourColor, 1.0);
}

修改下片段著色器

源代碼

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末凰盔,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子倦春,更是在濱河造成了極大的恐慌廊蜒,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件溅漾,死亡現場離奇詭異,居然都是意外死亡著榴,警方通過查閱死者的電腦和手機添履,發(fā)現死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來脑又,“玉大人暮胧,你說我怎么就攤上這事∥属铮” “怎么了往衷?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長严卖。 經常有香客問我席舍,道長,這世上最難降的妖魔是什么哮笆? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任来颤,我火速辦了婚禮,結果婚禮上稠肘,老公的妹妹穿的比我還像新娘福铅。我一直安慰自己,他們只是感情好项阴,可當我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布滑黔。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪略荡。 梳的紋絲不亂的頭發(fā)上庵佣,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天,我揣著相機與錄音撞芍,去河邊找鬼秧了。 笑死,一個胖子當著我的面吹牛序无,可吹牛的內容都是我干的验毡。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼帝嗡,長吁一口氣:“原來是場噩夢啊……” “哼晶通!你這毒婦竟也來了?” 一聲冷哼從身側響起哟玷,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤狮辽,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后巢寡,有當地人在樹林里發(fā)現了一具尸體喉脖,經...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年抑月,在試婚紗的時候發(fā)現自己被綠了树叽。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡谦絮,死狀恐怖题诵,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情层皱,我是刑警寧澤性锭,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站叫胖,受9級特大地震影響草冈,放射性物質發(fā)生泄漏。R本人自食惡果不足惜瓮增,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一疲陕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧钉赁,春花似錦蹄殃、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽讳苦。三九已至,卻和暖如春吩谦,著一層夾襖步出監(jiān)牢的瞬間鸳谜,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工式廷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留咐扭,地道東北人。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓滑废,卻偏偏與公主長得像蝗肪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蠕趁,可洞房花燭夜當晚...
    茶點故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內容