1 纹理的基本概念
1.1 什么是纹理?
在计算机图形学中,纹理是一个用于增强三维物体外观细节的2D图像(也有1D和3D纹理),它可以被想象为一张带有图案的"皮肤"或"墙纸",包裹在3D模型的表面。从技术角度看,纹理本质上是一个存储图像数据的内存结构,通常包含以下信息:
// 伪代码
struct Texture {
char* buffer; // 存储图像数据的buffer
int width; // 图像的宽
int height; // 图像的高
int format; // 图像格式,如:RGBA、RGB、YUV等
};
下面的图片展示了我们是如何把纹理坐标映射到三角形上的。

纹理解决了计算机图形学中的一个重要问题:如何在不过度增加模型复杂度的前提下为物体添加丰富的表面细节。如果没有纹理技术,想要绘制具有复杂外观的物体,就需要为每个微小细节创建相应的几何顶点,这会带来巨大的性能开销和开发难度。
1.2 纹理映射的工作原理
纹理映射是将2D纹理图像"贴"到3D模型表面的过程。这个过程需要一种坐标映射机制,使纹理上的每个点都能对应到模型表面的特定位置。这就是纹理坐标(UV坐标)的作用。

当渲染过程开始时,顶点着色器处理每个顶点的位置和纹理坐标信息,光栅化阶段对三角形内的像素进行插值计算,最终在片段着色器中使用插值后的UV坐标从纹理中采样颜色值。
1.3 纹理与着色器
纹理与着色器紧密协作完成渲染过程。在顶点着色器中,我们接收并传递纹理坐标;在片段着色器中,我们使用采样器(sampler)根据纹理坐标从纹理中获取颜色值。这种分工合作使得纹理映射能够高效地进行。
2 理解UV坐标系统
2.1 UV坐标的本质
UV坐标(又称纹理坐标)是连接2D纹理与3D模型表面的桥梁。它们定义了纹理图像上的点如何对应到3D模型表面的顶点。UV坐标系是一个2D坐标系,其中:
- U代表水平方向(范围通常[0,1])
- V代表垂直方向(范围通常[0,1])
为什么叫UV?因为XYZ已经被三维空间坐标使用,所以选取了字母表中的前两个字母U和V来表示这两个维度。在某些情况下,还会使用W表示深度维度,形成UVW坐标系,这在3D纹理中特别有用。
2.2 纹理坐标映射示例
假设有一个正方形模型和一张纹理图片,它们的对应关系如下:
| 3D模型顶点坐标 (x,y,z) | 对应的UV坐标 (u,v) | 纹理位置 |
|---|---|---|
| (0,0,0) | (0,0) | 纹理左下角 |
| (1,0,0) | (1,0) | 纹理右下角 |
| (1,1,0) | (1,1) | 纹理右上角 |
| (0,1,0) | (0,1) | 纹理左上角 |
当渲染这个正方形时,纹理会被拉伸覆盖整个表面,形成完整的纹理映射效果。
2.3 UV展开的艺术
对于复杂模型(如人物角色),需要将3D模型表面"展开"成2D平面,这个过程称为UV展开(UV Unwrapping)。这类似于将地球仪展开成世界地图,会产生接缝。
常见的UV布局类型有:
| UV布局类型 | 特点 | 适用场景 |
|---|---|---|
| 网格布局 | 规则划分 | 自动纹理生成 |
| 棋盘格布局 | 类似展开盒子 | 简单物体 |
| 自由布局 | 专业软件优化无拉伸 | 角色模型、复杂表面 |
| 三平面映射 | 3方向投影混合 | 地形、自然物体 |
UV展开是一个需要技巧的过程,目标是尽量减少纹理拉伸和接缝的影响,同时最大化利用纹理空间。
3 图像读取与纹理API详解
3.1 使用stb_image加载图像
stb_image.h是Sean Barrett的一个非常流行的单头文件图像加载库,它能够加载大部分流行的文件格式,并且能够很简单得整合到你的工程之中。将这个头文件以stb_image.h的名字加入你的工程,并另创建一个新的C++文件,输入以下代码:
使用stb_image加载图像的基本步骤:
- 在包含头文件前定义
STB_IMAGE_IMPLEMENTATION - 调用
stbi_load函数加载图像 - 处理图像数据
- 使用完成后释放内存
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
// 加载图像
int width, height, channels;
unsigned char* data = stbi_load("image.png", &width, &height, &channels, 0);
if (data) {
// 处理图像数据...
stbi_image_free(data); // 释放内存
}
需要注意的是,不同图形API的纹理坐标系可能存在差异。OpenGL的纹理坐标原点在左下角,而大多数图像的坐标原点在左上角。可以使用stbi_set_flip_vertically_on_load(true)函数进行垂直翻转,确保纹理正确显示。

3.2 核心纹理API解析
OpenGL提供了一系列函数用于创建和管理纹理:
3.2.1 纹理对象管理
在OpenGL中,纹理对象的管理是高效使用纹理的关键。它主要涉及纹理对象的生成、绑定、激活、参数设置以及销毁。下面这个表格汇总了这些核心操作及其用途:
| 操作类型 | 函数名 | 主要参数 | 用途描述 |
|---|---|---|---|
| 生成纹理 | glGenTextures | n: 数量, &texture: 存储纹理ID的地址 | 生成一个或多个纹理对象名称(ID),代表显存中的纹理资源。 |
| 绑定纹理 | glBindTexture | target: 纹理目标, texture: 纹理ID | 将纹理对象绑定到当前激活的纹理单元,使其成为当前操作的纹理。 |
| 激活纹理单元 | glActiveTexture | textureUnit: 纹理单元(如 GL_TEXTURE0) | 激活指定的纹理单元,后续的纹理绑定操作将作用于这个单元。 |
| 删除纹理 | glDeleteTextures | n: 数量, &texture: 要删除的纹理ID的地址 | 删除一个或多个纹理对象,释放其占用的显存资源。 |
-
生成纹理对象 (glGenTextures)
使用glGenTextures来生成新的纹理对象ID。这个ID是一个整数值,代表显存中的一个纹理资源。GLuint textureID; // 定义一个变量来存储纹理ID glGenTextures(1, &textureID); // 生成1个纹理,并将其ID存储到textureID中glGenTextures仅生成纹理名称(ID),并不立即创建纹理数据存储或设置纹理状态。实际的纹理资源通常在第一次绑定并配置(如使用glTexImage2D)时创建。
-
激活纹理单元 (glActiveTexture)
OpenGL提供了多个纹理单元(通常至少16个),允许你在着色器中同时使用多个纹理。glActiveTexture用于激活指定的纹理单元,后续的纹理绑定操作(glBindTexture)将作用于这个激活的单元。glActiveTexture(GL_TEXTURE0); // 激活纹理单元0 glActiveTexture(GL_TEXTURE1); // 激活纹理单元1- 纹理单元的名称是预定义的常量,如
GL_TEXTURE0、GL_TEXTURE1等。 - 纹理单元是纹理操作的“位置”。你必须在绑定纹理之前激活正确的纹理单元。
- 纹理单元的名称是预定义的常量,如
-
绑定纹理对象 (glBindTexture)
glBindTexture用于将纹理对象绑定到当前激活的纹理单元的特定目标上(如GL_TEXTURE_2D)。绑定后,所有后续针对该目标的纹理操作(如设置参数、上传图像数据)都会影响到这个绑定的纹理对象。glBindTexture(GL_TEXTURE_2D, textureID); // 将textureID绑定到当前激活纹理单元的GL_TEXTURE_2D目标上- 绑定概念:可以理解为将纹理对象“安装”到纹理单元的一个特定“插槽”(目标)上,以便GPU在渲染时使用。
- 解绑纹理可以通过绑定纹理ID为0实现:
glBindTexture(GL_TEXTURE_2D, 0)。
-
设置纹理参数
纹理对象绑定后,通常需要为其设置参数,这些参数控制纹理的过滤方式、环绕模式等,直接影响纹理的渲染效果。// 设置纹理缩小和放大过滤器 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 设置纹理坐标的环绕方式 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);- 常用过滤器:
GL_NEAREST(邻近过滤,像素化)、GL_LINEAR(线性过滤,平滑)。 - 常用环绕模式:
GL_REPEAT(重复)、GL_CLAMP_TO_EDGE(边缘拉伸)。
- 常用过滤器:
-
删除纹理对象 (glDeleteTextures)
当纹理对象不再需要时,应使用glDeleteTextures删除它们以释放显存资源。glDeleteTextures(1, &textureID); // 删除1个纹理对象- 注意:删除操作应在纹理对象不再被使用后进行,例如在程序结束或确定该纹理不会再被绑定和采样时。尝试渲染一个已删除的纹理会导致未定义行为。
- 删除后,对应的纹理ID可能会被后续的
glGenTextures调用再次分配。
💡 纹理对象管理最佳实践
- 生命周期管理:理想的做法是在应用程序初始化时集中创建和设置纹理,在渲染循环中仅进行绑定操作,避免在渲染循环中频繁创建和销毁纹理对象,以免引起性能瓶颈。
- 状态查询:OpenGL 提供了
glGetIntegerv等函数来查询当前绑定的纹理等状态,这在调试时非常有用。GLint currentTexture; glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤tTexture); - 多纹理使用:在片段着色器中同时使用多个纹理(如漫反射贴图、镜面光贴图、法线贴图)时,需要为每个纹理分别绑定到不同的纹理单元(如
GL_TEXTURE0,GL_TEXTURE1),并在着色器中通过sampler2Duniform变量和对应的纹理单元位置来正确采样。// 应用代码中激活和绑定多个纹理 glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, diffuseMap); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, specularMap); // 在着色器中声明采样器,并通过glUniform1i设置其对应的纹理单元 uniform sampler2D diffuseMap; // 对应纹理单元0 uniform sampler2D specularMap; // 对应纹理单元1 - 错误处理:确保在调用纹理相关函数前已创建并正确绑定纹理对象,错误管理纹理生命周期是常见的错误来源。
有效地管理纹理对象对于创建高效、视觉丰富的OpenGL应用程序至关重要。正确使用这些函数能确保纹理资源被合理分配、使用和释放。
3.2.2 纹理数据传递
glTexImage2D函数用于将图像数据上传到GPU的纹理对象中:
void glTexImage2D(
GLenum target, // 纹理目标(GL_TEXTURE_2D等)
GLint level, // 细节级别(0表示基本级别)
GLint internalformat, // 纹理内部格式(GL_RGB、GL_RGBA等)
GLsizei width, // 纹理宽度
GLsizei height, // 纹理高度
GLint border, // 边框宽度(必须为0)
GLenum format, // 像素数据格式(GL_RGB、GL_RGBA等)
GLenum type, // 像素数据类型(GL_UNSIGNED_BYTE等)
const void* data // 图像数据指针
);
3.2.3 多级渐远纹理生成
glGenerateMipmap(target)函数自动为纹理生成多级渐远纹理(Mipmap),这是一系列逐渐缩小的纹理图像,用于提高渲染质量和性能。
4 纹理对象创建实践
4.1 完整的纹理创建流程
下面是一个完整的纹理创建过程:
void prepareTexture() {
// 1. 使用stbImage读取图片
int width, height, channels;
// 反转y轴(OpenGL纹理坐标原点在左下角,图片原点在左上角)
stbi_set_flip_vertically_on_load(true);
// 加载图像,强制使用4通道(RGBA)
unsigned char* data = stbi_load("assets/textures/goku.jpg",
&width, &height, &channels,
STBI_rgb_alpha);
if (!data) {
std::cerr << "Failed to load texture" << std::endl;
return;
}
// 2. 生成纹理对象
glGenTextures(1, &texture);
// 激活纹理单元(默认激活0号单元,此步可选的)
glActiveTexture(GL_TEXTURE0);
// 绑定纹理对象
glBindTexture(GL_TEXTURE_2D, texture);
// 3. 传输纹理数据到GPU显存
glTexImage2D(GL_TEXTURE_2D,
0, // 细节级别
GL_RGBA, // 内部格式
width,
height,
0, // 边框宽度
GL_RGBA, // 像素数据格式
GL_UNSIGNED_BYTE, // 像素数据类型
data); // 图像数据指针
// 4. 生成多级渐远纹理
glGenerateMipmap(GL_TEXTURE_2D);
// 5. 释放客户端内存中的图像数据
stbi_image_free(data);
// 6. 设置纹理过滤方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
// 7. 设置纹理环绕方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // U方向
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // V方向
// 8. 解绑纹理(可选,避免后续操作意外修改)
glBindTexture(GL_TEXTURE_2D, 0);
}
4.2 错误处理与最佳实践
在实际项目中,纹理创建过程需要添加适当的错误处理:
- 检查图像加载是否成功:确保
stbi_load返回有效指针 - 检查纹理尺寸:确保纹理尺寸符合GPU要求(通常是2的幂次方)
- 检查内部格式支持:确保使用的纹理格式被当前GPU支持
- 内存管理:及时释放不再需要的图像数据
// 检查纹理尺寸是否是2的幂次方
bool isPowerOfTwo(int value) {
return (value & (value - 1)) == 0;
}
if (!isPowerOfTwo(width) || !isPowerOfTwo(height)) {
std::cout << "Warning: Texture dimensions are not power of two" << std::endl;
}
5 纹理过滤方式深入解析
5.1 纹理过滤的基本概念
纹理过滤解决的核心问题是:当纹理图像的分辨率与目标物体的分辨率不一致时,如何计算片段颜色。这种不一致通常发生在两种情况下:
- 放大(Magnify):纹理分辨率小于屏幕区域分辨率
- 缩小(Minify):纹理分辨率大于屏幕区域分辨率
OpenGL提供了多种纹理过滤算法,最重要的两种是GL_NEAREST(邻近过滤)和GL_LINEAR(线性过滤)。

5.2 GL_NEAREST过滤方式
GL_NEAREST(邻近过滤)是OpenGL默认的纹理过滤方式。当设置为GL_NEAREST时,OpenGL会选择中心点最接近纹理坐标的那个纹理像素。
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

特点:
- 产生颗粒状的图案
- 能够清晰看到组成纹理的像素
- 适合像素艺术或需要保留锐利边缘的场景
- 性能开销较小
5.3 GL_LINEAR过滤方式
GL_LINEAR(线性过滤)会基于纹理坐标附近的纹理像素,计算出一个插值,近似出这些纹理像素之间的颜色。一个纹理像素的中心距离纹理坐标越近,那么这个纹理像素的颜色对最终的样本颜色的贡献越大。
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

特点:
- 产生更平滑的图案,很难看出单个的纹理像素
- 提供更真实的视觉效果
- 适合大多数3D游戏和图形应用
- 性能开销略大于GL_NEAREST
5.4 多级渐远纹理与过滤组合
物体有远近之分,远处的物体看起来小,产生的片段少。为了节约内存且让小物体更真实,OpenGL使用不同的多级渐远纹理(就是一系列的纹理图像,后一个纹理是前一个纹理的二分之一),根据不同的距离选择不同的纹理图像取样。
在使用多级渐远纹理的时候,不同级别的纹理层之间会产生不真实的生硬边界,这时候可以使用纹理过滤方式,指定不同多级渐远纹理级别之间的过滤方式有4种:
| 过滤方式 | 描述 |
|---|---|
| GL_NEAREST_MIPMAP_NEAREST | 使用最邻近的多级渐远纹理级别,并使用邻近插值进行纹理采样 |
| GL_LINEAR_MIPMAP_NEAREST | 使用最邻近的多级渐远纹理级别,并使用线性插值进行采样 |
| GL_NEAREST_MIPMAP_LINEAR | 在两个最匹配像素大小的多级渐远纹理之间进行线性插值,使用邻近插值采样 |
| GL_LINEAR_MIPMAP_LINEAR | 在两个最匹配的多级渐远纹理之间使用线性插值,并使用线性插值进行采样 |

// 常用设置:缩小使用线性Mipmap线性过滤,放大使用线性过滤
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
注意:多级渐远纹理只适用于纹理缩小的情况,为放大过滤设置多级渐远纹理选项会产生错误。
6 纹理环绕方式详解
6.1 纹理坐标超出范围的问题
纹理坐标的范围通常是[0, 1],但当纹理坐标超出这个范围时,OpenGL需要知道如何处理这种情况。OpenGL提供了多种纹理环绕(Wrapping)方式来解决这个问题。
6.2 四种主要的环绕方式
OpenGL提供了四种纹理环绕方式,可以使用glTexParameteri函数进行设置:

6.2.1 GL_REPEAT(重复)
对纹理的默认行为,重复纹理图像。
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
特点:
- 纹理在表面上无限重复
- 适合地板、墙面等需要重复图案的场景
6.2.2 GL_MIRRORED_REPEAT(镜像重复)
和GL_REPEAT一样,但每次重复图片是镜像放置的。
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
特点:
- 纹理重复时会产生镜像效果
- 可以减少重复图案的明显接缝
6.2.3 GL_CLAMP_TO_EDGE(边缘拉伸)
纹理坐标会被约束在0到1之间,超出的部分会重复纹理坐标的边缘,产生一种边缘被拉伸的效果。
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
特点:
- 超出的部分会拉伸边缘像素
- 适合不希望显示重复图案的场景
6.2.4 GL_CLAMP_TO_BORDER(边框颜色)
超出的坐标为用户指定的边缘颜色。
// 首先设置环绕方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
// 然后设置边框颜色
float borderColor[] = { 1.0f, 1.0f, 0.0f, 1.0f }; // RGBA黄色
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
特点:
- 超出的部分显示指定的边框颜色
- 适合需要突出显示纹理边界的场景
6.3 环绕方式的应用场景
不同的环绕方式适用于不同的场景:
| 环绕方式 | 应用场景 | 视觉效果 |
|---|---|---|
| GL_REPEAT | 地板、墙面、天空盒 | 无缝重复的图案 |
| GL_MIRRORED_REPEAT | 需要减少接缝的重复图案 | 镜像重复的图案 |
| GL_CLAMP_TO_EDGE | 单次出现的纹理,不希望重复 | 边缘拉伸的效果 |
| GL_CLAMP_TO_BORDER | 需要突出显示边界的纹理 | 自定义颜色的边框 |
7 采样器与纹理单元的使用
7.1 采样器(Sampler)的基本概念
在片段着色器中,采样器(Sampler)是一种特殊类型的uniform变量,用于从纹理中读取颜色数据。采样器代表了纹理的访问状态和过滤方式,是连接着色器与纹理对象的桥梁。
在GLSL中声明一个2D纹理采样器:
uniform sampler2D sampler;
7.2 纹理单元与着色器交互
7.2.1 纹理单元的工作原理
OpenGL通过纹理单元(Texture Unit)管理系统来管理多个纹理。每个纹理单元是一个独立的纹理状态容器,可以绑定一个纹理对象并保存其过滤、环绕等状态信息。
默认情况下,OpenGL至少提供16个纹理单元(从GL_TEXTURE0到GL_TEXTURE15),现代GPU通常支持更多纹理单元。
7.2.2 在着色器中使用纹理
下面是一个完整的片段着色器示例,演示了如何使用采样器进行纹理采样:
#version 460 core
out vec4 FragColor;
in vec3 color; // 输入颜色(从顶点着色器传递)
in vec2 uv; // 输入纹理坐标(从顶点着色器传递)
uniform sampler2D sampler; // 2D纹理采样器
void main()
{
// 使用texture函数从采样器获取颜色
vec4 texColor = texture(sampler, uv);
// 可以将纹理颜色与其他颜色因素混合
FragColor = vec4(color, 1.0) * texColor;
}
7.2.3 在应用程序中设置采样器
在OpenGL应用程序中,需要将纹理单元与采样器uniform变量关联起来:
void render() {
// 清理画布
glClear(GL_COLOR_BUFFER_BIT);
// 使用着色器程序
shader->begin();
// 将采样器绑定到纹理单元0
shader->setInt("sampler", 0);
// 激活纹理单元0
glActiveTexture(GL_TEXTURE0);
// 将纹理对象绑定到当前纹理单元
glBindTexture(GL_TEXTURE_2D, texture);
// 绑定VAO
glBindVertexArray(vao);
// 绘制图形
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
// 解绑VAO
glBindVertexArray(0);
// 结束使用着色器
shader->end();
}
7.3 多纹理渲染技术
现代图形应用通常需要同时使用多个纹理(漫反射贴图、法线贴图、高光贴图等)。以下是一个多纹理渲染的示例:
#version 460 core
out vec4 FragColor;
in vec2 uv;
in vec3 normal;
in vec3 fragPos;
// 多个纹理采样器
uniform sampler2D diffuseMap; // 漫反射贴图
uniform sampler2D normalMap; // 法线贴图
uniform sampler2D specularMap; // 高光贴图
// 光源信息
uniform vec3 lightPos;
uniform vec3 viewPos;
void main() {
// 从各个纹理中采样
vec3 diffuseColor = texture(diffuseMap, uv).rgb;
vec3 normalValue = texture(normalMap, uv).rgb;
float specularIntensity = texture(specularMap, uv).r;
// 简化的光照计算
vec3 norm = normalize(normalValue * 2.0 - 1.0);
vec3 lightDir = normalize(lightPos - fragPos);
vec3 viewDir = normalize(viewPos - fragPos);
vec3 reflectDir = reflect(-lightDir, norm);
// 漫反射光照
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * diffuseColor;
// 镜面光照
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32.0);
vec3 specular = specularIntensity * spec * vec3(1.0);
// 环境光照(简化的)
vec3 ambient = 0.1 * diffuseColor;
// 最终颜色
FragColor = vec4(ambient + diffuse + specular, 1.0);
}
在应用程序中设置多个纹理单元:
// 绑定多个纹理
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, diffuseTexture);
shader->setInt("diffuseMap", 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, normalTexture);
shader->setInt("normalMap", 1);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, specularTexture);
shader->setInt("specularMap", 2);
8 总结
通过本文的详细讲解,我们全面了解了OpenGL纹理技术的各个方面。从纹理的基本概念到UV坐标系统,从图像加载到纹理对象创建,从过滤方式到环绕模式,最后到采样器与纹理单元的使用,我们建立了一个完整的纹理知识体系。
纹理技术是实时图形渲染的基石,掌握好纹理技术对于创建逼真且高效的图形应用至关重要。随着现代图形API的发展,纹理技术也在不断演进,出现了许多高级纹理技术如数组纹理、立方体贴图、压缩纹理等,这些都是在掌握了本文基础知识后的进一步学习方向。
希望本文能够帮助读者深入理解OpenGL纹理技术,并在实际项目中灵活运用这些知识,创造出更加精彩和逼真的图形应用。

2697

被折叠的 条评论
为什么被折叠?



