种类
2D纹理
2D纹理数组:独立切片
3D纹理:切片关联依赖
立方图纹理
2D纹理
就是一个图像数据的二维数组。一个纹理的单独数据元素称作纹素,纹素通过基本格式和数据类型确定的。
基本格式 | 描述 |
GL_RED | 红 |
GL_RG | 红绿 |
GL_RGB | 红绿蓝 |
GL_RGBA | 红绿蓝、alpha |
GL_LUMINANCE | 亮度 |
GL_LUMINANCE_ALPHA | 亮度、alpha |
GL_ALPHA | alpha |
GL_DEPTH_COMPONENT | 深度 |
GL_DEPTH_STENCIL | 深度、模板 |
GL_RED_INTEGER | 整数红 |
GL_RG_INTEGER | 整数红绿 |
GL_RGB_INTEGER | 整数红绿蓝 |
GL_RGBA_INTEGER | 整数红绿蓝、alpha |
纹理对象和纹理的加载
void glGenTextures(GLsizei n, GLuint *textures)
//GL_TEXTURE_2D
//GL_TEXTURE_3D
//GL_TEXTURE_2D_ARRAY
//GL_TEXTURE_CUBE_MAP
void glBindTexture(GLenum targtet, GLuint texture)
void glTexImage2D(GLenum target,
GLint level,
Genum internalFormat, //纹理存储的内部格式
GLsizei with,
GLsizei height,
GLint border, //忽略,值为0
GLenum format, //输出的纹理格式
GLenum type, //输入像素数据的类型GL_UNSIGNED_BYTE GL_BYTE GL_UNSIGNED_SHORT……
const void* pixedls)//包含实际图像的像素数据
void glDeleteTextures(GLsizei n, GLuint *textures)
// Texture object handle
GLuint textureId;
// 2x2 Image, 3 bytes per pixel (R, G, B)
GLubyte pixels[4 * 3] =
{
255, 0, 0, // Red
0, 255, 0, // Green
0, 0, 255, // Blue
255, 255, 0 // Yellow
};
//设置解包对齐。通过glTexImage2D上传纹理数据时,像素行被认定为对齐到GL_UNPACK_ALIGNMENT设置的值
//默认情况下,该值为4,意味着像素行被认定为从4字节的编边界开始。
//此处设置为1,意味着每个像素行从字节编解开始(紧密打包)。
//几乎不使用GL_UNPACK_ALIGNMENT之外的选项
//打包选项由glReadPixedls使用·
glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 );
// Generate a texture object
glGenTextures ( 1, &textureId );
// Bind the texture object
glBindTexture ( GL_TEXTURE_2D, textureId );
// Load the texture
glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels );
// Set the filtering mode
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
纹理过滤和mip贴图
mip贴图链始于原来指定的图像,后续的每个图像在每个维度上是前一个图像的一半,一直持续到最后达到链底部的1x1纹理。mip贴图级别可以编程生成,一个mip级别中的每个像素通常根据上一级别中相同位置的4个像素的平均值计算(盒式过滤)----目的是解决伪像,减少性能损失。
纹理坐标包装
glTexParameter[i|f][v]设置
- GL_TEXTURE_WRAP_S:设置s坐标
- GL_TEXTURE_WRAP_T:设置t坐标
- GL_TEXTURE_WRAP_R:设置r坐标,只用于3D纹理和2D纹理数组
纹理包装模式
- GL_REPEAT:重复纹理
- GL_CLAMP_TO_EDGE:限定读取纹理的边缘
- GL_MIRRORED_REPEAT:重复纹理和镜像
//简单调用
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT );
着色器程序中使用2D纹理
char vShaderStr[] =
"#version 300 es \n"
"layout(location = 0) in vec4 a_position; \n"
"layout(location = 1) in vec2 a_texCoord; \n"
"out vec2 v_texCoord; \n"
"void main() \n"
"{ \n"
" gl_Position = a_position; \n"
" v_texCoord = a_texCoord; \n"
"} \n";
char fShaderStr[] =
"#version 300 es \n"
"precision mediump float; \n"
"in vec2 v_texCoord; \n"
"layout(location = 0) out vec4 outColor; \n"
"uniform sampler2D s_texture; \n"
"void main() \n"
"{ \n"
" outColor = texture( s_texture, v_texCoord ); \n"
"} \n";
GLuint textId;
//创建program,textureId过程省略
//…………
//获取坐标
GLuint tex_position = glGetUniformLocation ( program, "s_texture" );
//指定0代表指定采样器从GL_TEXTURE0读取数据,指定1则代表TEXTURE1
glUniform1i(tex_position, 0);
//指定活动单元
glActiveTexture(GL_TEXURE0);
//绑定textId到活动单元
glBindTexture(GL_TEXTURE_2D, textId);
//后续可对纹理进行缩放包装处理
立方图纹理使用
使用samplerCube声明三个分量的纹理坐标,代码相似度较高
3D纹理和2D纹理数组
使用glTexImage3D加载纹理数组,代码相似度较高
压缩纹理
- 可减少内存占用;
- 节约了着色器中读取纹理时耗时的内存宽带;
- 较少必须储存的图像数据,减少应用程序的下载大小;
2.0未定义压缩的纹理图像格式,所以各厂商可能实现不同的纹理压缩格式。
3.0定义了厂商必须支持的标准纹理压缩格式,ETC2和EAC(不支持3D纹理,只支持2D纹理和2D纹理数组)。
glCompressedTexImage2D:用于加载2D纹理和立方图压缩图像数据。
glCompressedTexImage3D: 2D纹理数组,可用于加载供应商专用的3D纹理压缩格式
更新纹理部分区域
glTexSubImage2D() :更新图像的一个子区域
target 纹理目标
level 指定更新的mip级别,纹理贴图level
xoffset 纹理数据的偏移x值
yoffset 纹理数据的偏移y值
width 宽
height 高
format 像素数据的颜色格式
type 颜色分量的数据类型
pixels 包含图像子区域的实际像素数据
glCompressedTexSubImage2D:更新压缩的2D纹理图像的子区域
glTexSubImage3D:更新3D纹理和2D纹理数组的子区域
从颜色缓冲区中复制纹理数据
注:帧缓冲区对象提供了渲染-纹理转换的快速方法,比复制图像数据更快,性能高。
glReadBuffer(GLenum mode): GL_BACK GL_COLOR_ATTACHMEMTi GL_NONE
glCopyTexImage2D、glCopuTexSubImage2D、glCopyTexSubImage3D
复制颜色缓冲区的数据时,可以转换为分量较少的格式,但不能转换为分量较多的格式。
采样器对象(3.0):为了改善性能
2.0频繁使用glTexParameter指定纹理参数时会造成不必要的开销,因为程序中会有大量纹理使用相同的设置。
3.0引入了采样器对象,将采样器状态与纹理状态分离,一次函数调用中与纹理单元绑定使用。采样器对象可用于很多纹理。
api基本见名知意
glGenSamplers(GLsizei n, GLuint *samplers);
glDeleteSamplers;
glBindSampler;
glSamplerParameteri;
glSamplerParameteriv;
glSamplerParameterf;
glSamplerParameterfv;
不可变纹理3.0:为了改善性能
应用程序在加载数据之前指定纹理的格式和大小。
glBindTexture绑定纹理后,使用glTexStorage2D、glTexStorage3D分配不可变存储。
生成不可变纹理后,调用gltexImage*、glCompressedTexImage*、glCopuTexImage*、glTexStorage*将无效,生成GL_INVALID_OPERATION错误。
但可以使用glTexSubImage2D、glTexSubImage3D、glGenerateMipMap或者渲染到纹理加载图像数据。