OpenGL之纹理数组和无绑定纹理

最近要学习纹理数组,网上查了下资料并不多,可能是本身用到就比较少吧,正好学习了下也算补充下笔记了。

首先,纹理数组有两种:

目录

sampler2DArray textures

sampler2D textures[16]


1.sampler2DArray textures

从网上搜索的结果来看,第一种用的可能是更多的。sampler2DArray也是个类型,和普通单张纹理不一样的地方可能这是一个纹理集合体吧。所以,它在绑定纹理时也只需要一个纹理ID,使用时也是一个纹理单元,和普通单张纹理绑定和使用是一样的,只是在创建加载纹理时有些差别,具体从代码里看:

              //生成纹理
                glGenTextures(1, &textureID);
                //绑定纹理
                glBindTexture(GL_TEXTURE_2D_ARRAY, textureID); //绑定时选择纹理数组类型
                //设置如何从数据缓冲区去读取图像数据
                glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
                //设置纹理过滤的参数
                glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
                glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT);
                glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                
                //接下来就是不同的地方了--
                //两种分配方式都可以,glTexImage3D好像是老版本的方式
                glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 1000, 1000, 2);
                //glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 1000, 1000, 2, 0,GL_RGB, GL_UNSIGNED_BYTE, NULL);
                
                const char* path[2] = { "D:\\My Document\\1213.jpg","D:\\My Document\\R-C.jpg" };
                //加载图片
                for (int i = 0; i < 2; i++) {
                        unsigned char* pBits;
                        int nWidth, nHeight, nComponents;

                        // Read the texture bits 读取纹理数据
                        stbi_set_flip_vertically_on_load(true); //告诉stb_image.h在y轴上翻转加载的纹理。

                        pBits = stbi_load(path, &nWidth, &nHeight, &nComponents, 0);

                        //更新纹理 这里把深度进行了修改,下面的i就代表深度
                        glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, i, nWidth, nHeight, 1, GL_RGB, GL_UNSIGNED_BYTE, pBits);
                        stbi_image_free(pBits);
                }

纹理使用时:

                glActiveTexture(GL_TEXTURE2);
                glBindTexture(GL_TEXTURE_2D_ARRAY, textureID);
                glUniform1i(glGetUniformLocation(programObject[0], "TextureArray"), 2);//纹理传入binding=2

着色器纹理使用:

#version 430 core

out vec4 FragColor;
in vec2 vTexPosition1;

layout(binding = 2) uniform sampler2DArray TextureArray;

void main()
{
    FragColor = texture(TextureArray, vec3(vTexPosition1,1));//纹理坐标第三位为纹理序号索引
}

经过加载不同纹理发现,如果尺寸大于设置的尺寸,纹理就加载不出来了,尺寸小了也会出现填不满的现象,所以个人以为,这种方式可能只适合加载统一尺寸的多张纹理。

2.sampler2D textures[16]

这一种就是真正意义的纹理数组了,起初我以为可以像传入普通数组一样传入纹理,并用glUniform1iv去传入,但是我不知道此刻应该先绑定哪一个纹理ID,尝试下来都没有成功加载。之后又通过UBO的方式将纹理ID数组传入,依然没有加载出纹理。之后学习无绑定纹理,才了解到纹理与着色器的联系并不是通过纹理ID,所以索性通过无绑定的方式加载纹理数组。

        GLuint textureArray[3]; //纹理数组
        //此处省略纹理创建过程
        //.....
        //
        GLuint64 handles[3]; //纹理句柄
        for (int i = 0; i < 3; i++)
        {
            glBindTexture(GL_TEXTURE_2D, textureArray[i]);
            handles[i] = glGetTextureHandleARB(textureArray[i]);
            glMakeTextureHandleResidentARB(handles[i]);
        }

使用纹理时有两种,我都尝试了:

//第一种--单独的纹理数组--uniform sampler2D textArray[3];
glUniformHandleui64vARB(glGetUniformLocation(programObject[0], "textArray"), 3,handles);
//第二种--被UBO包裹的纹理数组
//glBindBuffer(GL_UNIFORM_BUFFER, UBO);
//glBufferSubData(GL_UNIFORM_BUFFER, 0, 3*sizeof(GLuint64), &handles);

着色器里写法:

#version 430 core
#extension GL_ARB_bindless_texture : require //无绑定纹理必须要有的
out vec4 FragColor;

in vec2 vTexPosition1;

//第一种--单独的纹理数组
//uniform sampler2D textArray[3];

//第二种--被UBO包裹的纹理数组
layout(binding = 0) uniform UBO_data
{
    sampler2D textArray[3];
};

void main()
{
    //纹理采样
    FragColor = texture(textArray[0], vTexPosition1);//以数组成员方式采样
}

经过试验发现,这种方式加载的纹理尺寸可以不受限制了,而且加载出来都可以自适应窗口。

之后想尝试绑定的方式加载,如果有大佬有办法,看到的话希望可以指点一下。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值