读取图像

在使用纹理前,我们需要将读取对应的图像文件到CPU并对其进行解析。然而OpenGL作为图形API并不提供读取、解析图像文件的功能,因此我们需要自己实现或调用第三方库,这里就以第三方项目stb stb_image为例。

引入stb_image

通过官方仓库下载:https://github.com/nothings/stb/blob/master/stb_image.h

CPP
#define STB_IMAGE_IMPLEMENTATION // 引入前需要定义该宏
#include "stb_image.h"
点击展开查看更多

读取图像

C
// 8位色深
unsigned char *stbi_load(
	char const *filename,
	int *x,
	int *y,
	int *comp,
	int req_comp,
)
// 16位色深
unsigned short *stbi_load_16( /* 参数8位相同 */)
点击展开查看更多
C
unsigned char *data; // 存数据
int width = 0; // 存宽
int height = 0; // 存高
int PicType = 0; // 存图像类型
unsigned char *buf = stbi_load(img_path, &width, &height, &PicType, STBI_default);
if (PicType == STBI_rgb) {
	const unsigned int buf_size = width * height * 4; // 数据长度(注意通道数量!)
	// ...
}
stbi_image_free(buf); // 注意释放内存
点击展开查看更多

注意

  1. 图像数据*buf的长度为长 ✕ 宽 ✕ 通道数
  2. 图像数据*buf需要调用函数stbi_image_free进行释放

创建纹理

示例

C
GLuint texture;
glGenTextures(1, &texture); // 创建纹理对象
glBindTexture(GL_TEXTURE_2D, texture); // 绑定纹理对象
/* 设置纹理参数 */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // X轴上环绕方式为Repeat
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Y轴上环绕方式为Repeat
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // 纹理缩小时使用邻近过滤
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 纹理放大时使用线性过滤
/* - */
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf); // 上传图像到GPU
glGenerateMipmap(GL_TEXTURE_2D); // 生成Mipmap(可选)
glBindTexture(GL_TEXTURE_2D, 0); // 解绑纹理对象
点击展开查看更多

创建纹理对象

C
void glGenTextures(GLsizei n, GLuint * textures)
点击展开查看更多

绑定纹理对象

C
void glBindTexture(GLenum target, GLuint texture);
点击展开查看更多

设置纹理参数

设置纹理的各种参数,通常需要设置 纹理环绕纹理过滤 -> [纹理环绕 和 纹理过滤](/posts/纹理环绕 和 纹理过滤) 具体参数过多,参考:glTexParameter - OpenGL 4 Reference Pages

上传图像

C
void glTexImage2D(
	GLenum target,
	GLint level,
	GLint internalformat,
	GLsizei width,
	GLsizei height,
	GLint border,
	GLenum format,
	GLenum type,
	const void *data,
);
点击展开查看更多

使用纹理

示例

C
glActiveTexture(GL_TEXTURE0); // 激活纹理单元0
glBindTexture(GL_TEXTURE_2D, texture1); // 绑定纹理对象
glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture1"), 0); // 设置Uniform
glActiveTexture(GL_TEXTURE1); // 或者 GL_TEXTURE0 + 1
glBindTexture(GL_TEXTURE_2D, texture2);
glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture2"), 1);
点击展开查看更多
  1. 设置sampler2D类型的Uniform前需要先激活纹理单元,并绑定纹理对象(不需要解绑),最后将纹理单元编号传入Uniform
  2. 注意Uniform设置的内容是纹理单元编号
  3. 纹理单元Active后不需要手动关闭
  4. OpenGL保证最差的硬件至少有16个纹理单元可用

释放纹理对象

C
void glDeleteTextures(GLsizei n, const GLuint * textures);
点击展开查看更多

纹理目标

纹理目标 (Texture Target) 维度 描述 主要用途 特点
GL_TEXTURE_1D 1D 单行像素数据 渐变、高度图 使用 s 坐标采样
GL_TEXTURE_2D 2D 标准二维图像 贴图、渲染目标 最常用,支持Mipmap
GL_TEXTURE_3D 3D 体积数据(体素) 医学成像、烟雾 采样需要 (s, t, r) 坐标
GL_TEXTURE_1D_ARRAY 1D+Layer 多个1D纹理组合 动画序列、批量1D数据 通过 (s, layer) 访问
GL_TEXTURE_2D_ARRAY 2D+Layer 多个2D纹理堆叠 地形图集、帧动画 通过 (s, t, layer) 访问
GL_TEXTURE_RECTANGLE 2D (非归一化) 任意尺寸的2D纹理 屏幕后处理、临时存储 不支持Mipmap,使用像素坐标
GL_TEXTURE_CUBE_MAP 立方体 (6面) 6个2D纹理组成立方体 天空盒、环境反射 采样使用3D方向向量 (s, t, r)
GL_TEXTURE_CUBE_MAP_ARRAY 立方体+Layer 多个立方体贴图 动态环境反射、VR 通过 (s, t, r, layer) 访问
GL_TEXTURE_BUFFER (TBO) 1D (Buffer) 绑定到缓冲区对象 大数据流(如粒子系统) 尺寸大,但采样功能有限
GL_TEXTURE_2D_MULTISAMPLE 2D (MSAA) 多重采样抗锯齿纹理 抗锯齿渲染 采样由硬件处理,无Mipmap
GL_TEXTURE_2D_MULTISAMPLE_ARRAY 2D+Layer (MSAA) 多重采样纹理数组 分层抗锯齿(VR/立体渲染) 通过 (s, t, layer) 访问

版权声明

作者: Cheyne Xie

链接: https://chaim.eu.org/posts/%E7%BA%B9%E7%90%86/

许可证: CC BY-NC-SA 4.0

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Please attribute the source, use non-commercially, and maintain the same license.

开始搜索

输入关键词搜索文章内容

↑↓
ESC
⌘K 快捷键