OpenGL ES 高级进阶:纹理数组

栏目: 后端 · 发布时间: 6年前

内容简介:大家好,这是我的今天给大家介绍一下在这个

大家好,这是我的 OpenGL ES 高级进阶系列文章,在我的 github 上有一个与本系列文章对应的项目,欢迎关注,链接: github.com/kenneycode/…

今天给大家介绍一下 纹理数组 ,它是 OpenGL ES 3.0 引入的一个新特性,它能让我们以数组的方式往 shader 中传递纹理,我们先来看看一个普通的 fragment shader

#version 300 es
precision mediump float;
layout(location = 0) out 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 定了,里面支持的纹理数量也就定了,不利于各种数量的纹理,除非自己去生成 shader 。 纹理数组的出现让我们可以像传递一个数组一样将纹理传给 shader ,我们来看一下使用纹理数组时的 shader

// vertex shader
#version 300 es
precision mediump float;
layout(location = 0) in vec4 a_Position;
layout(location = 1) in 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 = 0) out 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 ,表示它是一个数组,然后使用的时候,也是 texture(u_texture, v_textureCoordinate) ,似乎看越来和不使用纹理数组时一样?其实不一样,也许细心的朋友发现了差别, v_textureCoordinate 此时是 vec3 而不是 vec2 了,我们知道纹理坐标是二维的,这里 vec3 的第三维就是取对应的纹理,可以理解成是数组的下标。 我们还能看到,纹理数组不需要在 shader 先声明数组的大小,它是在代码里控制的,这样就很灵活,我们来看看代码是怎样写的,大部分的操作和使用普通纹理时一样(可参考我的另一篇文章: 《Android OpenGL ES 2.0 手把手教学(6)- 纹理》 ),不一样的地方是首先绑定纹理时的类型不一样:

// 创建图片纹理数组
// 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 ,另外,还要像给数组分配空间一样给纹理数组分配大小:

GLES30.glTexStorage3D(GLES30.GL_TEXTURE_2D_ARRAY, 1, GLES30.GL_RGBA8, 390, 270, 2)
复制代码

比如在我们的例子中,我们创建了一个大小为2的纹理数组,每个纹理的大小是390*270,这里用的 APIglTexStorage3D ,实际上还有一种纹理叫3D纹理,它和纹理数组有些类似,我们使用纹理数组的时候,有些 API 就是使用了操作3D纹理时的 API

接下来我们就把2张图片加载到我们的纹理数组中:

// 通过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, 0, 0, 0, i, bitmap.width, bitmap.height, 1, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, b)
    bitmap.recycle()
}
复制代码

这步操作和我们使用单个纹理时很类似,单个纹理时是用 glTexImage2D ,这里是用 glTexSubImage3D 并且需要指定当前是给纹理数组的哪层纹理载入数据。

我们前面提到, 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
                                    )
复制代码

另外,在这里我将顶点坐标设置为左下角和右上角,因此会在左下角和右上角分配渲染纹理数组中的第0个和第1个纹理,效果如下:

OpenGL ES 高级进阶:纹理数组

代码在我 githubOpenGLESPro 项目中,本文对应的是 SampleTextureArray ,项目链接: github.com/kenneycode/…

感谢阅读!


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

构建之法(第三版)

构建之法(第三版)

邹欣 / 人民邮电出版社 / 2017-6 / 69.00元

软件工程牵涉的范围很广, 同时也是一般院校的同学反映比较空洞乏味的课程。 但是,软件工程 的技术对于投身 IT 产业的学生来说是非常重要的。作者有在世界一流软件企业 20 年的一线软件开 发经验,他在数所高校进行了多年的软件工程教学实践,总结出了在 16 周的时间内让同学们通过 “做 中学 (Learning By Doing)” 掌握实用的软件工程技术的教学计划,并得到高校师生的积极反馈。在此 ......一起来看看 《构建之法(第三版)》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

html转js在线工具
html转js在线工具

html转js在线工具