TexCoords
是表示模型顶点的纹理坐标的归一化坐标,范围通常在 [0, 1]
之间。通常用于将 2D 纹理图像映射到 3D 模型表面,对应纹理图像的 u
和 v
坐标(即将图像在水平和竖直方向归一化到[0,1]送进 vec2 TexCoords
)。
Assimp 负责从模型文件中解析顶点的纹理坐标,并将其存储在 mTextureCoords
中。通过 OpenGL 的顶点、片段着色器,将这些坐标用于纹理采样。
u
和 v
的含义
u
:纹理在水平方向(x 轴)的归一化坐标。v
:纹理在竖直方向(y 轴)的归一化坐标。- 纹理坐标
(u, v)
映射到 2D 纹理图的像素位置,用于从纹理中采样颜色。
纹理坐标的用途
-
将纹理坐标传递给 OpenGL 着色器 在 OpenGL 中,
TexCoords
作为顶点属性传递到片段着色器,用于采样纹理。 -
在片段着色器中采样颜色 通过纹理坐标
(u, v)
从绑定的纹理图像中采样颜色,并将颜色应用到模型的表面。
Assimp 提取 TexCoords
的方式:
在 Assimp 中,每个网格的顶点可能包含一个或多个纹理坐标集合,存储在 aiMesh
的 mTextureCoords
中。mTextureCoords
是一个指针数组,支持多个纹理集(最多 8 个)。一个常见场景是仅使用第一个纹理集 mTextureCoords[0]
。
代码示例
以下代码展示了如何从 Assimp 读取纹理坐标并用于 OpenGL 渲染。
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
#include <iostream>
#include <vector>
// 定义顶点结构
struct Vertex {
glm::vec3 Position; // 顶点位置
glm::vec3 Normal; // 顶点法向量
glm::vec2 TexCoords; // 纹理坐标 (u, v)
};
// 定义网格结构
struct Mesh {
std::vector<Vertex> vertices;
std::vector<unsigned int> indices;
};
Mesh loadMesh(const std::string& path) {
Assimp::Importer importer;
// 读取模型
const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs);
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) {
std::cerr << "Error::Assimp:: " << importer.GetErrorString() << std::endl;
exit(-1);
}
aiMesh* mesh = scene->mMeshes[0]; // 只加载第一个网格
Mesh result;
// 遍历顶点
for (unsigned int i = 0; i < mesh->mNumVertices; i++) {
Vertex vertex;
// 顶点位置
vertex.Position = glm::vec3(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z);
// 顶点法向量
if (mesh->HasNormals()) {
vertex.Normal = glm::vec3(mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z);
}
// 纹理坐标
if (mesh->mTextureCoords[0]) { // 检查是否存在第一个纹理集
vertex.TexCoords = glm::vec2(mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y);
} else {
vertex.TexCoords = glm::vec2(0.0f, 0.0f); // 默认值
}
result.vertices.push_back(vertex);
}
// 遍历索引
for (unsigned int i = 0; i < mesh->mNumFaces; i++) {
aiFace face = mesh->mFaces[i];
for (unsigned int j = 0; j < face.mNumIndices; j++) {
result.indices.push_back(face.mIndices[j]);
}
}
return result;
}
顶点着色器(Vertex Shader)
#version 330 core
layout (location = 0) in vec3 aPos; // 顶点位置
layout (location = 1) in vec2 aTexCoord; // 纹理坐标
out vec2 TexCoords; // 输出给片段着色器
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main() {
gl_Position = projection * view * model * vec4(aPos, 1.0);
TexCoords = aTexCoord; // 将纹理坐标传递给片段着色器
}
片段着色器(Fragment Shader)
#version 330 core
out vec4 FragColor;
in vec2 TexCoords; // 从顶点着色器传入的纹理坐标
uniform sampler2D texture1; // 绑定的纹理
void main() {
// 使用纹理坐标采样颜色
FragColor = texture(texture1, TexCoords);
}