Array Texture这个东西的意思是,一个纹理对象,可以存储不止一张图片信息,就是说是是一个数组,每个元素都是一张图片。这样免了频繁地去切换当前需要bind的纹理,而且可以节省系统资源。本文主要讨论的是2D array textures. 1D的使用很少 不讨论。

那么,在shader里面应该怎么去访问我想要的纹理呢?普通的纹理坐标是 (x,y) 这里就不够了,这里需要 (x,y,z) 三个值,XY代表2d纹理坐标,Z值代表选择读取哪一张纹理的数据,从0开始。

初始化Array Texture

普通 2D texture对象

初始化一个普通的2D纹理对象的方式是这样的:

genTexture-->BindTexture-->指定图片信息(使用 glTexImage2D 函数)

2D texture array对象

前两步一样的,指定图片信息的时候不一样。这里需要两歩操作,开辟存储空间和上传数据。

第一步,开辟空间:

爲纹理开辟内存,确定存储的结构

glTexImage3D (这个和glTexImage2D长得很像的函数)

target :GL_TEXTURE_2D_ARRAY

depth: 用于指定我们的数组的长度(若是3D texture就是纹理的深度信息了,我们用的是2D texture array)。

mipmap的level,一般我们给0,也就是說每次只能确定一个mipmap的level.

需要注意的是,我们生成普通纹理的时候数据是在这个地方指定的,同样,这个函数的最后一个参数也代表源像素数据,但是这里可以指定也可以写NULL,后面再上传数据。我推荐这样做。

以上是旧的做法,目前官方更推荐使用 glTexStorage3D 函数,功能类似。

glTexStorage3D — simultaneously specify storage for all levels of a three-dimensional or two-dimensional array texture

void glTexStorage3D( 	GLenum target,
GLsizei levels,
GLenum internalformat,
GLsizei width,
GLsizei height,
GLsizei depth);

参数和上面的相同,需要注意:levels 最小设置爲1;

这个函数比上面的好在什么地方呢?根据大牛的解释,glTexImage3D生成的纹理对象是不完整的,比如缺少mipmap的信息,缺少环绕方式等等,而且是可变的,这一秒创建好下一秒被改的乱七八糟了。而这个函数生成一个完整的不可变的对象,更可靠更安全。而且不用再显式地去调用glGenerateMipmap 。它已经自动帮你做好了处理。

第二步,指定数据

glTexSubImage3D

这个函数用于上传真正的纹理数据,参数较多,可以参考官方的文档。提供指定xyz的offset,即偏移量。一般xy的设置0,z方向的便宜就代表了是第几张纹理,所以这个需要按需要设置。后面的设置宽高很简单,然后是depth,这一次调用上传的数据的depth,如果两张纹理图片放在一起,然后一起上传(这样只需要调用一次这个函数),那么需要設爲2.后面再设置format data等等即可。如果需要指定mipmap(level大于1) 那么还需要把每个level的数据都上传。

Example:

TexStorage3D(...3... W, H, 2);
// allocates W x H x 2 level0, W/2 x H/2 x 2 level1, W/4 x H/4 x 2 level2.
// Contents are undefined at this point. TexSubImage3D(...level0, 0, 0, 0, W, H, 1... lod0_slice0_pixels);
TexSubImage3D(...level0, 0, 0, 1, W, H, 1... lod0_slice1_pixels);
TexSubImage3D(...level1, 0, 0, 0, W/2, H/2, 1... lod1_slice0_pixels);
TexSubImage3D(...level1, 0, 0, 1, W/2, H/2, 1... lod1_slice1_pixels);
TexSubImage3D(...level2, 0, 0, 0, W/4, H/4, 1... lod2_slice0_pixels);
TexSubImage3D(...level2, 0, 0, 1, W/4, H/4, 1... lod2_slice1_pixels);
// all slices of all mipmaps now transferred

如果相同mipmap的两张纹理是前后相连地存储在一起的,可以这样做:

TexSubImage3D(...level0, 0, 0, 0, W, H, 2... lod0_slice0and1_pixels);
TexSubImage3D(...level1, 0, 0, 0, W/2, H/2, 2... lod1_slice0and1_pixels);
TexSubImage3D(...level2, 0, 0, 0, W/4, H/4, 2... lod2_slice0and1_pixels);

shader内访问

需要定义2darray的sampler,然后还是调用texture函数,但是第二个参数需要三维的纹理坐标,z值代表在第几张纹理上面取值,从 0 开始。

"precision mediump sampler2DArray;\n"
"uniform sampler2DArray texture_array;\n"
...
...
" color = texture(texture_array, vec3(texCoord.xy, layer));\n"

注意:如果上传三维的纹理坐标,假设我们有两张纹理图片,我们上传的z值只有 0 和 1 两个,但是在光栅化阶段的插值计算会生成一些处于0和1之间的非整数的z值,这不是我们想要的,所以不能使用三维纹理坐标。我们需要单独上传这个数据,然后在shader内构造出一个新的三维的向量,这个时候z值就只有0、1两个值了。


参考资料:Array-Texture-confusion 讨论帖子

例子1--zwqxin

例子2--老外的

OpenGL ES: Array Texture初体验的更多相关文章

  1. [工作记录] Android OpenGL ES: non-square texture - continue

    previous: [工作记录] Android OpenGL ES 2.0: square texture not supported on some device recently I found ...

  2. 【ES】ElasticSearch初体验之使用Java进行最基本的增删改查~

    好久没写博文了, 最近项目中使用到了ElaticSearch相关的一些内容, 刚好自己也来做个总结. 现在自己也只能算得上入门, 总结下自己在工作中使用Java操作ES的一些小经验吧. 本文总共分为三 ...

  3. OpenGL ES: 纹理采样 texture sample

    Sampler (GLSL) Sampler通常是在Fragment shader(片元着色器)内定义的,这是一个uniform类型的变量,即处理不同的片元时这个变量是一致不变的.一个sampler和 ...

  4. [OpenGL ES 02]OpenGL ES渲染管线与着色器

    [OpenGL ES 02]OpenGL ES渲染管线与着色器 罗朝辉 (http://www.cnblogs.com/kesalin/) 本文遵循"署名-非商业用途-保持一致"创 ...

  5. [OpenGL ES 03]3D变换:模型,视图,投影与Viewport

    [OpenGL ES 03]3D变换:模型,视图,投影与Viewport 罗朝辉 (http://blog.csdn.net/kesalin) 本文遵循“署名-非商业用途-保持一致”创作公用协议 系列 ...

  6. Android OpenGL ES(十四)gl10方法解析

    Android 支持 OpenGL 列表 1.GL 2.GL 10 3.GL 10 EXT 4.GL 11 5.GL 11 EXT 6.GL 11 ExtensionPack 我们将使用 GL10 这 ...

  7. Android OpenGL ES(二)OpenGL ES管道(Pipeline) .

    大部分图形系统都可以比作工厂中的装配线(Assemble line)或者称为管道(Pipeline).前一道的输出作为下道工序的输入.主CPU发出一个绘图指令,然后可能由硬件部件完成坐标变换,裁剪,添 ...

  8. 一步步实现windows版ijkplayer系列文章之六——SDL2源码分析之OpenGL ES在windows上的渲染过程

    一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...

  9. OpenGL ES 3.0之VertexAttributes,Vertex Arrays,and Buffer Objects(九)

    顶点数据,也称为顶点属性,指每一个顶点数据.指能被用来描述每个顶点的数据,或能被所有顶点使用的常量值.例如你想绘制一个具有颜色的立方体三角形.你指定一个恒定的值用于三角形的所有三个顶点颜色.但三角形的 ...

随机推荐

  1. Microsoft Loves Linux

    微软新任CEO纳德拉提出的“Microsoft Loves Linux”,并且微软宣布.NET框架的开源,近期Microsoft不但宣布了Linux平台的SQL Server,还宣布了Microsof ...

  2. 15个关于Chrome的开发必备小技巧[译]

    谷歌Chrome,是当前最流行且被众多web开发人员使用的浏览器.最快六周就更新发布一次以及伴随着它不断强大的开发组件,使得Chrome成为你必备的开发工具.例如,在线编辑CSS,console以及d ...

  3. iOS逆向工程之Hopper+LLDB调试第三方App

    LLDB是Low Level Debugger的简称,在iOS开发的调试中LLDB是经常使用的,LLDB是Xcode内置的动态调试工具.使用LLDB可以动态的调试你的应用程序,如果你不做其他的额外处理 ...

  4. AFNetworking 3.0 源码解读(八)之 AFImageDownloader

    AFImageDownloader 这个类对写DownloadManager有很大的借鉴意义.在平时的开发中,当我们使用UIImageView加载一个网络上的图片时,其原理就是把图片下载下来,然后再赋 ...

  5. Asp.Net 操作XML文件的增删改查 利用GridView

    不废话,直接上如何利用Asp.NET操作XML文件,并对其属性进行修改,刚开始的时候,是打算使用JS来控制生成XML文件的,但是最后却是无法创建文件,读取文件则没有使用了 index.aspx 文件 ...

  6. [数据结构]——堆(Heap)、堆排序和TopK

    堆(heap),是一种特殊的数据结构.之所以特殊,因为堆的形象化是一个棵完全二叉树,并且满足任意节点始终不大于(或者不小于)左右子节点(有别于二叉搜索树Binary Search Tree).其中,前 ...

  7. Openfire集群源码分析

    如果用户量增加后为了解决吞吐量问题,需要引入集群,在openfire中提供了集群的支持,另外也实现了两个集群插件:hazelcast和clustering.为了了解情况集群的工作原理,我就沿着open ...

  8. 前端构建大法 Gulp 系列 (四):gulp实战

    前端构建大法 Gulp 系列 (一):为什么需要前端构建 前端构建大法 Gulp 系列 (二):为什么选择gulp 前端构建大法 Gulp 系列 (三):gulp的4个API 让你成为gulp专家 前 ...

  9. Linux 桌面美化那点事儿

    各个 Linux 桌面发行版刚拿到手的时候,或多或少都有点儿不满意,对它们进行一些改造是必须的.网上不乏各种 Linux 桌面美化的教程和经验贴,对我们这些 Linux 爱好者来说都是很好的参考资料. ...

  10. ASP.NET MVC 5 Web编程5 -- 页面传值的方式

    本篇文章将讲述MVC的页面传值方式,具体包括:后端向前端传值(Controller向View传值):前端向后端传值(View向Controller传值):Action与Action之间的传值. 回顾 ...