<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          OpenGL ES 高級進階:紋理數(shù)組

          共 8622字,需瀏覽 18分鐘

           ·

          2023-10-12 12:43

          今天給大家介紹一下紋理數(shù)組,它是OpenGL ES 3.0引入的一個新特性,它能讓我們以數(shù)組的方式往shader中傳遞紋理,我們先來看看一個普通的fragment shader

          #version 300 es
          precision mediump float;
          layout(location = 0out vec4 fragColor;
          layout(location = 0) uniform sampler2D u_texture;
          in vec2 v_textureCoordinate;
          void main() {
              fragColor = texture(u_texture, v_textureCoordinate);
          }

          在這個shader中我們聲明了一個uniform sampler2D變量,即我們只能傳遞一個紋理,如果要傳遞多個紋理,就要聲明多個uniform sampler2D

          #version 300 es
          precision mediump float;
          ...
          layout(location = 0) uniform sampler2D u_texture0;
          layout(location = 1) uniform sampler2D u_texture1;
          layout(location = 2) uniform sampler2D u_texture2;
          ...

          這樣一方面會占用多個紋理單元,另一方面一旦shader定了,里面支持的紋理數(shù)量也就定了,不利于各種數(shù)量的紋理,除非自己去生成shader。 

          紋理數(shù)組的出現(xiàn)讓我們可以像傳遞一個數(shù)組一樣將紋理傳給shader,我們來看一下使用紋理數(shù)組時的shader

          // vertex shader
          #version 300 es
          precision mediump float;
          layout(location = 0in vec4 a_Position;
          layout(location = 1in vec3 a_textureCoordinate;
          out vec3 v_textureCoordinate;
          void main() {
              v_textureCoordinate = a_textureCoordinate;
              gl_Position = a_Position;
          }

          // fragment shader
          #version 300 es
          precision mediump float;
          precision mediump sampler2DArray;
          layout(location = 0out vec4 fragColor;
          in vec3 v_textureCoordinate;
          layout(location = 0) uniform sampler2DArray u_texture;
          void main() {
              fragColor = texture(u_texture, v_textureCoordinate);
          }

          我們先來看fragment shader,可以看到,sampler2D變成了sampler2DArray,表示它是一個數(shù)組,然后使用的時候,也是texture(u_texture, v_textureCoordinate),似乎看越來和不使用紋理數(shù)組時一樣?

          其實不一樣,也許細心的朋友發(fā)現(xiàn)了差別,v_textureCoordinate此時是vec3而不是vec2了,我們知道紋理坐標是二維的,這里vec3的第三維就是取對應的紋理,可以理解成是數(shù)組的下標。 

          我們還能看到,紋理數(shù)組不需要在shader先聲明數(shù)組的大小,它是在代碼里控制的,這樣就很靈活,我們來看看代碼是怎樣寫的,大部分的操作和使用普通紋理時一樣

          (可參考我的另一篇文章:[《Android OpenGL ES 2.0 手把手教學(6)- 紋理》] https://juejin.cn/post/6844903834523811853)

          不一樣的地方是首先綁定紋理時的類型不一樣:

          // 創(chuàng)建圖片紋理數(shù)組
          // Create texture for image
          val textures = IntArray(1)
          GLES30.glGenTextures(textures.size, textures, 0)
          imageTexture = textures[0]

          // 注意這里是GL_TEXTURE_2D_ARRAY
          // Note that the type is GL_TEXTURE_2D_ARRAY
          GLES30.glBindTexture(GLES30.GL_TEXTURE_2D_ARRAY, textures[0])

          普通紋理是按GL_TEXTURE_2D的類型綁定的,這里是GL_TEXTURE_2D_ARRAY,另外,還要像給數(shù)組分配空間一樣給紋理數(shù)組分配大小:

          GLES30.glTexStorage3D(GLES30.GL_TEXTURE_2D_ARRAY, 1, GLES30.GL_RGBA8, 3902702)

          比如在我們的例子中,我們創(chuàng)建了一個大小為2的紋理數(shù)組,每個紋理的大小是390*270,這里用的APIglTexStorage3D,實際上還有一種紋理叫3D紋理,它和紋理數(shù)組有些類似,我們使用紋理數(shù)組的時候,有些API就是使用了操作3D紋理時的API。

          接下來我們就把2張圖片加載到我們的紋理數(shù)組中:

          // 通過glTexSubImage3D指定每層的紋理
          // Specify the texture of each layer via glTexSubImage3D
          for (i in 0 until 2) {
              val bitmap = Util.decodeBitmapFromAssets("image_$i.jpg")
              val b = ByteBuffer.allocate(bitmap.width * bitmap.height * 4)
              bitmap.copyPixelsToBuffer(b)
              b.position(0)
              GLES30.glTexSubImage3D(GLES30.GL_TEXTURE_2D_ARRAY, 000, i, bitmap.width, bitmap.height, 1, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, b)
              bitmap.recycle()
          }

          這步操作和我們使用單個紋理時很類似,單個紋理時是用glTexImage2D,這里是用glTexSubImage3D并且需要指定當前是給紋理數(shù)組的哪層紋理載入數(shù)據。

          我們前面提到,v_textureCoordinate此時是vec3而不是vec2了,因此我們傳的紋理坐標也要相應的變化:

          // 紋理坐標
          // The texture coordinate
          private val textureCoordinateData = floatArrayOf(
                                                  0f, 1f, 0f, 
                                                  0f, 0f, 0f, 
                                                  1f, 0f, 0f, 
                                                  0f, 1f, 0f, 
                                                  1f, 0f, 0f, 
                                                  1f, 1f, 0f,
                                                  0f, 1f, 1f, 
                                                  0f, 0f, 1f, 
                                                  1f, 0f, 1f, 
                                                  0f, 1f, 1f, 
                                                  1f, 0f, 1f, 
                                                  1f, 1f, 1f
                                              )

          另外,在這里我將頂點坐標設置為左下角和右上角,因此會在左下角和右上角分配渲染紋理數(shù)組中的第0個和第1個紋理,效果如下:

          代碼在我githubOpenGLESPro項目中,本文對應的是SampleTextureArray,項目鏈接:https://github.com/kenneycode/OpenGLESPro

          感謝閱讀!

          原文鏈接: https://juejin.cn/post/6844903846678888461

          -- END --


          進技術交流群,掃碼添加我的微信:Byte-Flow 



          獲取相關資料和源碼


          推薦:

          Android FFmpeg 實現(xiàn)帶濾鏡的微信小視頻錄制功能

          全網最全的 Android 音視頻和 OpenGL ES 干貨,都在這了

          一文掌握 YUV 圖像的基本處理

          抖音傳送帶特效是怎么實現(xiàn)的?

          所有你想要的圖片轉場效果,都在這了

          面試官:如何利用 Shader 實現(xiàn) RGBA 到 NV21 圖像格式轉換?

          我用 OpenGL ES 給小姐姐做了幾個抖音濾鏡


          項目疑難問題解答、大廠內部推薦、面試指導、簡歷指導、代碼指導、offer 選擇建議、學習路線規(guī)劃,可以點擊找我一對一解答。

          瀏覽 638
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  小说乱伦视频网站 | 黄色在线播放视频免费 | 二三区视频 | 国产成人精品一区二区三区四区五区 | 高清无码免费视频 |