赞
踩
最近要学习纹理数组,网上查了下资料并不多,可能是本身用到就比较少吧,正好学习了下也算补充下笔记了。
首先,纹理数组有两种:
目录
从网上搜索的结果来看,第一种用的可能是更多的。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));//纹理坐标第三位为纹理序号索引
- }
经过加载不同纹理发现,如果尺寸大于设置的尺寸,纹理就加载不出来了,尺寸小了也会出现填不满的现象,所以个人以为,这种方式可能只适合加载统一尺寸的多张纹理。
这一种就是真正意义的纹理数组了,起初我以为可以像传入普通数组一样传入纹理,并用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);//以数组成员方式采样
- }

经过试验发现,这种方式加载的纹理尺寸可以不受限制了,而且加载出来都可以自适应窗口。
之后想尝试绑定的方式加载,如果有大佬有办法,看到的话希望可以指点一下。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。