IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android OpenGL_ES glActiveTexture和glBindTexture -> 正文阅读

[移动开发]Android OpenGL_ES glActiveTexture和glBindTexture

Refrence:

  1. https://blog.csdn.net/n5/article/details/90045648
  2. https://blog.csdn.net/hankern/article/details/112058229
  3. https://blog.csdn.net/huazi5dgan/article/details/76160334
  4. https://blog.csdn.net/zhuyingqingfen/article/details/19968341
  5. https://blog.csdn.net/candycat1992/article/details/8974719

简单的理解:GPU(显卡)中有N个 texture unit 纹理单元(具体数量依赖你的GPU能力),每个 texture unit 纹理单元(GL_TEXTURE0、GL_TEXTURE1…)都有GL_TEXTURE_1D、GL_TEXTURE_2D等textureTarget纹理目标接口。

Android系统默认有从GL_TEXTURE0GL_TEXTURE3132个纹理单元,不过不同的平台或不同的系统,可用的纹理单元数量是不同的。

比如,在Pixel3XL+Android11上,可用的TextureUnit共有96个:

// [GL_TEXTURE0 ~ GL_TEXTURE31 + 64]
// "(不在这个区间就会打印警告“bindTextureImage: clearing GL error: 0x500”)"
GLES20.glActiveTexture(GL_TEXTURE0); 

glActiveTexture函数

默认情况下当前活跃的纹理单元为0,即如果不调用glActiveTexture函数,默认使用纹理单元0。

struct TextureUnit
{
    GLuint targetTexture1D;
    GLuint targetTexture2D;
    GLuint targetTexture3D;
    GLuint targetTextureCube;
    ...
};
 
TextureUnit textureUnits[GL_MAX_TEXTURE_IMAGE_UNITS]
GLuint currentTextureUnit = 0;

从下面代码中可以看到:当调用glBindTexture绑定纹理对象到纹理目标时,所作用的是当前活跃的纹理单元:

void glActiveTexture(GLenum textureUnit)
{
    currentTextureUnit = textureUnit  - GL_TEXTURE0 ;
}

void glBindTexture(GLenum textureTarget, GLuint textureObject)
{
    TextureUnit *texUnit = &textureUnits[currentTextureUnit];
    switch(textureTarget)
    {
    case GL_TEXTURE_1D: texUnit->targetTexture1D = textureObject; break;
    case GL_TEXTURE_2D: texUnit->targetTexture2D = textureObject; break;
    case GL_TEXTURE_3D: texUnit->targetTexture3D = textureObject; break;
    case GL_TEXTURE_CUBEMAP: texUnit->targetTextureCube = textureObject; break;
    }
}

glBindTexture函数

glBindTexture — 将一个命名的纹理绑定到一个纹理目标上

//这个更好理解 void glBindTexture(GLenum textureTarget, GLuint textureObject)
void glBindTexture(GLenum  target, GLuint  texture); 
  • target

    纹理对象要绑定到的目标。必须是下面中的一个:GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_BUFFER, GL_TEXTURE_2D_MULTISAMPLE 或者 GL_TEXTURE_2D_MULTISAMPLE_ARRAY。

  • texture

    纹理对象(纹理对象分配号),取值范围为Integer.MIN_VALUEInteger.MAX_VALUE,可通过glGenTextures得到。

int[] textures = new int[3];
GLES20.glGenTextures(textures.length, textures, 0);
// SurfaceTexture texture = new SurfaceTexture(textures[0]);
// texture.detachFromGLContext(); // 不调用会抛异常
// texture.attachToGLContext(textures[1]);
// 将surfaceTexture纹理对象附加到当前的GLContext上下文中
// surfaceTexture纹理对象在当前GLContext上下文中的分配号是textures[0]
surfaceTexure.attachToGLContext(textures[0]);
...
// 选择当前活动的纹理单元,不调用此代码默认使用纹理单元0
GLES20.glActiveTexture(GL_TEXTURE0);
// 将分配号为textures[0]的纹理对象绑定到当前活动纹理单元的纹理目标GLES11Ext.GL_TEXTURE_EXTERNAL_OES上
// 纹理对象分配号的取值为Integer.MIN_VALUE~Integer.MAX_VALUE
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textures[0]);
...

当一张纹理被绑定后,GL对于这个纹理目标的操作都会影响到这个被绑定的纹理。也就是说,这个纹理目标成为了被绑定到它上面的纹理的别名,而纹理名称为0则会引用到它的默认纹理。之后可能还会调用如下方法:

glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,512,512,0,GL_RGBA, GL_UNSIGNED_BYTE,NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

这些函数里面的GL_TEXTURE_2D就等价与我们之前绑定的纹理,所以我们对GL_TEXTURE_2D的操作就会影响到之前的纹理,这和C++中的引用有点类似。

glBindTexture的使用方法实际上体现在两个地方:

  • 首先是第一次载入纹理对象时,将载入的纹理对象(int型的纹理分配号)与纹理单元绑定在一起。也就是给当前的纹理分配相应的纹理号。
  • 其次是载入多个纹理之后,需要在多个纹理之间进行切换,此时也需要使用glBindTexture函数进行切换。(这里是有正确? 应该是可通过需要glActiveTexture切换)

  • 在openGL中,存在一系列的texture unit,通过 glActiveTexture 选择当前的texture unit默认的unit是0。而当前的texture unit中存在多个texture target,例如GL_TEXTURE_2D, GL_TEXTURE_CUBEMAP…。

  • 通过glCreateTexture创建texture object后,第一次调用glBindTexture时,决定了texture object的类型,比如调用的是glBindTexture(GL_TEXTURE_2D,0),那么这个texture object就是一个2D texture,其内部状态被初始化为2D texture的状态,它不能再被bind到其他类型的texture target上,否则会产生运行时错误。

  • 通过glBindTexture将一个texture object绑定到当前激活的texture unit的texture target上。然后通过glTexImage2D, glTexParameteri等函数改变texture object的状态。

  • 创建texture object的时候需要指定texture unit吗?

    并不需要,无论当前是哪个texture unit,不影响创建texture object。创建好的texture object可以绑定到其他texture unit的texture target上使用。

  • 什么时候需要关心texture unit?

    当使用多重纹理的时候,也就是说在shader里面要同时使用多于一个sampler的时候。通过glUniform1i将texture unit传给sampler,让sampler知道应该去哪个texture unit中获取texture object,那么应该获取哪个texture target指向的texture object呢?这就要看sampler的类型了。比如sampler2D,就会获取sampler被指向的texture unit中的GL_TEXTURE_2D texture targert。

总结:

openGL中纹理的状态分为texture unit和texture object包含的状态。texture unit的状态包括当前激活的unit,每个unit下面的各个target分别指向哪些texture object。texture object的状态包含type, texParam, format等等。

什么时候需要调用glActiveTexture以及glBindTexture就要看状态是否会改变。

对于shader来说,他可以访问所有的texture unit中指定的texture object。只要你告诉他某个sampler使用哪个unit就行。如果每个unit的内容指定后不需要改变,则即便shader使用了多个sampler也不需要来回切换unit的状态。当然更常见的是渲染完一个pass后,需要改变当前texture unit中某target中的texture object,也就是需要换贴图了。那么标准的操作就是先glActiveTexture,然后glBindTexture。当然如果你只使用unit0,则不需要调用glActiveTexture。


  • glActiveTexture负责选择当前活跃的纹理单元
  • glBindTexture负责使用纹理单元中的某一种纹理类型

一个纹理单元可以有多种纹理类型GL_TEXTURE_1D、GL_TEXTURE_2D等,但是只能使用一种,不可以多种同时使用。或者可以理解为纹理单元有多种绑定点,但一次只能绑定到一种类型上。给着色器上传的是纹理单元号。

调用顺序:先调用glActiveTexture,再调用glBindTexture

如果使用了帧缓冲区,则调用顺序为glBindFramebuffer、glBindTexture,不需要glActiveTexture

glBindFramebuffer后调用glActiveTexture会有什么效果,应该没有直接影响,但是glActiveTexture会影响纹理贴图,进而会影响渲染到帧缓冲区中的内容。

也就是glBindFramebuffer是确定画布,glActiveTexture是确定绘画的颜料。


glActiveTexture glBindTexture glUniform1i关系图

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-01 14:37:31  更:2021-08-01 14:37:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/7 8:11:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码