OpenGL ES: Array Texture初体验
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初体验的更多相关文章
- [工作记录] Android OpenGL ES: non-square texture - continue
previous: [工作记录] Android OpenGL ES 2.0: square texture not supported on some device recently I found ...
- 【ES】ElasticSearch初体验之使用Java进行最基本的增删改查~
好久没写博文了, 最近项目中使用到了ElaticSearch相关的一些内容, 刚好自己也来做个总结. 现在自己也只能算得上入门, 总结下自己在工作中使用Java操作ES的一些小经验吧. 本文总共分为三 ...
- OpenGL ES: 纹理采样 texture sample
Sampler (GLSL) Sampler通常是在Fragment shader(片元着色器)内定义的,这是一个uniform类型的变量,即处理不同的片元时这个变量是一致不变的.一个sampler和 ...
- [OpenGL ES 02]OpenGL ES渲染管线与着色器
[OpenGL ES 02]OpenGL ES渲染管线与着色器 罗朝辉 (http://www.cnblogs.com/kesalin/) 本文遵循"署名-非商业用途-保持一致"创 ...
- [OpenGL ES 03]3D变换:模型,视图,投影与Viewport
[OpenGL ES 03]3D变换:模型,视图,投影与Viewport 罗朝辉 (http://blog.csdn.net/kesalin) 本文遵循“署名-非商业用途-保持一致”创作公用协议 系列 ...
- 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 这 ...
- Android OpenGL ES(二)OpenGL ES管道(Pipeline) .
大部分图形系统都可以比作工厂中的装配线(Assemble line)或者称为管道(Pipeline).前一道的输出作为下道工序的输入.主CPU发出一个绘图指令,然后可能由硬件部件完成坐标变换,裁剪,添 ...
- 一步步实现windows版ijkplayer系列文章之六——SDL2源码分析之OpenGL ES在windows上的渲染过程
一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...
- OpenGL ES 3.0之VertexAttributes,Vertex Arrays,and Buffer Objects(九)
顶点数据,也称为顶点属性,指每一个顶点数据.指能被用来描述每个顶点的数据,或能被所有顶点使用的常量值.例如你想绘制一个具有颜色的立方体三角形.你指定一个恒定的值用于三角形的所有三个顶点颜色.但三角形的 ...
随机推荐
- iOS开发系列--Swift语言
概述 Swift是苹果2014年推出的全新的编程语言,它继承了C语言.ObjC的特性,且克服了C语言的兼容性问题.Swift发展过程中不仅保留了ObjC很多语法特性,它也借鉴了多种现代化语言的特点,在 ...
- 认识 Azure
本文为官网摘录总结
- C#中如何在Excel工作表创建混合型图表
在进行图表分析的时候,我们可能需要在一张图表呈现两个或多个样式的图表,以便更加清晰.直观地查看不同的数据大小和变化趋势.在这篇文章中,我将分享C#中如何在一张图表中创建不同的图表类型,其中包括如何在同 ...
- CSS 3 学习——渐变
通过CSS渐变创建的是一个没有固定比例和固定尺寸的<image>类型,也就是说是一张图片,这张图片的尺寸由所应用的元素的相关信息决定.凡是支持图片类型的CSS属性都可以设置渐变,而支持颜色 ...
- golang struct扩展函数参数命名警告
今天在使用VSCode编写golang代码时,定义一个struct,扩展几个方法,如下: package storage import ( "fmt" "github.c ...
- Android开发学习—— Fragment
#Fragment* 用途:在一个Activity里切换界面,切换界面时只切换Fragment里面的内容* 生命周期方法跟Activity一致,可以理解把其为就是一个Activity* 定义布局文件作 ...
- Linux基础介绍【第五篇】
linux权限位 Linux文件或目录的权限位是由9个权限位来控制,每三位为一组,它们分别是文件属主权限.属组权限.其他用户权限. r:read可读权限,对应数字4: w:write可写权限,对应数字 ...
- Jquery 获得当前标签的名称和标签属性
得到标签的名称 $("#name").prop("tagName"); 或者 $("#name")[0].tagName; 注意:1.得到的 ...
- Configure a bridge interface over a VLAN tagged bonded interface
SOLUTION VERIFIED February 5 2014 KB340153 Environment Red Hat Enterprise Linux 6 (All Versions) Red ...
- AutoMapper使用中的问题
指定值只会执行一次 public class MomanBaseProfile : Profile { public MomanBaseProfile() { CreateMap<Request ...