第六章 纹理
6.1 纹理映射
- 在应用程序中使用纹理映射的步骤:
- 创建一个纹理对象,为它加载纹素数据
- 为顶点增加纹理坐标
- 把纹理图与着色器中将要使用的纹理采样器关联
- 在着色器中使用纹理采样器来查询纹素值
6.2 基本纹理类型
- 每个纹理对象标识组成完整纹理的一组图像
- 每个图像可以是纹素的1维、2维或者3维数组
- 数组纹理–纹理包含1维或者2维切片的数组,数组的每个元素是一个切片
- 纹理可以使用用于2维和2维数组纹理的多重采样的纹理类型来表示多重采样表面
- 多重采样是一个用于抗锯齿的术语,其中每个纹素(或者像素)被赋予多个独立的颜色,然后再渲染过程中合并这些颜色来生成最终的输出颜色;多重采样纹理对于每个纹素都有几个采样
- 纹理通过纹理单元绑定到OpenGL环境,其中纹理单元用命名为GL_TEXTURE0~i的绑定点来表示
- 只要有一个纹理被绑定到OpenGL环境,则在着色器中可以使用采样器变量来访问,采样器变量用匹配纹理的维数来声明
- 纹理维数(称为纹理目标)和对应的采样器类型如下:
目标 GL_TEXTURE* | 采样器类型 | 维度 |
---|---|---|
1D | sampler1D | 1D |
1D_ARRAY | sampler1DArray | 1D数组 |
2D | sampler2D | 2D |
2D_ARRAY | sampler2DArray | 2D数组 |
2D_MULTISAMPLE | sampler2DMS | 2D多重采样 |
2D_MULTISAMPLE_ARRAY | sampler2DMSArray | 2D多重采样数组 |
3D | sampler3D | 3D |
CUBE | samplerCube | 立方体映射纹理 |
ARRAY | samplerCubeArray | 立方体映射数组 |
RECTANGLE | samplerRect | 2D矩形 |
BUFFER | samplerBuffer | 1D缓存 |
- 矩形纹理对象(GL_TEXTURE_RECTANGLE)是2维纹理的特例,表示一个简单的纹素的矩形,它没有mipmap,并且不能表示纹理数组;一些纹理模式(texture wrapping)不支持矩形纹理
- 缓冲纹理(GL_TEXTURE_BUFFER)表示任意纹素的1维数组;没有mipmap,不能聚合数组;缓冲纹理的存储实际是用一个缓冲对象来表示,因此它的上边界大小比普通的1维纹理大的多;缓冲纹理可以使任意着色器阶段的数据访问而不用把它拷贝进纹理图像
6.3 创建和初始化纹理
-
OpenGL中使用纹理的第一步:为纹理对象保留名称并把它们绑定到环境的纹理单元
-
void glGenTextures(GLsizei n, GLuint* textures)
在数组textures中返回n个用于纹理对象的当前没有使用的名称
标记textures中的名称为被使用,它们只有在第一次绑定的时候,才能获取到纹理状态和维数(比如1D、2D或者3D)
0是保留的纹理名,从来不会被glGenTextures()返回 -
void glBindTexture(GLenum target, GLuint texture) 做三件事:
- 当第一次使用无符号整数值texture且不是0时,创建一个新的纹理对象并赋给那个名称
- 当绑定先前创建的纹理对象时,将激活这个纹理对象
- 当绑定texture值为0时,OpenGL将删除与激活的纹理单元特定目标关联的所有的绑定,不留下任何绑定
target的取值如上表,其中只有立方体纹理有些不同:GL_TEXTURE_CUBE_MAP、GL_TEXTURE_CUBE_MAP_ARRAY
-
OpenGL环境支持多个纹理单元,调用glBindTexture()将纹理对象绑定到激活的纹理单元,维数用target设置;激活的纹理单元可以用glActiveTexture()函数来改变;
-
一个纹理可以同时绑定到多个纹理单元,这使相同的纹理数据通过表示绑定纹理的纹理单元的不同采样器来读取
-
void glActiveTexture(GLenum texture) 设置当前激活的纹理单元
-
GLboolean glIsTexture(GLuint texture) 如果texture是已经被绑定的纹理的名称并且还没有被删除,返回GL_TRUE;如果texture是0或者不存在的纹理名称返回GL_FALSE
-
void glDeleteTexture(GLsizei n, const GLuint* textures) 删除n个使用数组textures的元素来命名的纹理对象
-
创建纹理对象后,必须为它们设置存储和最后的数据;纹理对象的每1维都有相关的决定纹理边界的存储函数,它们是glTexStorage1D()、glTexStorage2D()和glTexStorage3D(),分别维1维、2维和3维纹理定义存储;对于数组纹理,用下一个更高维来设置数组的大小
-
void glTexStorage1D(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width) target必须是GL_TEXTURE_1D
-
void glTexStorage2D(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height) 如果target是GL_TEXTURE_2D,则为2维纹理设置存储,width和height设置纹理的大小;如果是GL_TEXTURE_1D_ARRAY,则为1维纹理数组设置存储,width设置纹理的范围,height设置数组中切片的数目
-
void glTexStorage3D(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth) 如果target是GL_TEXTURE_3D,则为3维纹理设置存储,width、height和depth为像素数组设置大小;如果是GL_TEXTURE_2D_ARRAY,则为2维数组纹理设置存储,width和height为每个切片设置大小,depth设置数组中切片的数目;
-
上边三个函数为纹理创建固定的存储;纹理存储的属性包括可以选择的内部格式、纹理的所有mipmap级像素所需的内存量;这只是存储的属性,只要指定的纹理为不可改变,那么存储不能改变;纹理的内容可以使用glTexSubImage2D()来改变
-
上边三个函数只允许为单采样纹理创建存储;如果采用的是多重采样纹理,则要使用glTexStorage2DMultisample()或者glTexStorage3DMultisample()为纹理创建存储
-
void glTexStorage2DMultisample(GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations)
为当前绑定到target的2维多重采样纹理对象设置纹理存储;target必须是GL_TEXTURE_2D_MULTISAMPLE;width和height设置纹理的大小;samples设置纹理采样的数目;如果fixedsamplelocation是GL_TRUE,那么OpenGL为纹理中每个纹素的相同样本使用相同的子纹素位置;如果是GL_FALSE,那么OpenGL为每个纹素给定的样本选择空间变化的位置 -
void glTexStroage3DMultisample(GLenum target, GLsizei samples, GLenum