From 9cc36af3f04535ef8253082e8c9a3c87ab1b947b Mon Sep 17 00:00:00 2001 From: atdunbg Date: Wed, 23 Sep 2026 19:35:06 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E9=87=91=E5=B1=9E=E6=B8=B2=E6=9F=93?= =?UTF-8?q?=E5=A1=91=E6=96=99=E6=84=9F=E2=80=94=E2=80=94glTF=20MR=20?= =?UTF-8?q?=E8=B4=B4=E5=9B=BE=E6=9C=AA=E5=8A=A0=E8=BD=BD=20+=20UV=20?= =?UTF-8?q?=E7=BF=BB=E8=BD=AC=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - assimp 5.x glTF2 importer 把 MR 合图落在 METALNESS(15)/ DIFFUSE_ROUGHNESS(16),不是 UNKNOWN(18)——此前 metallic 恒 0 全走电介质路径。槽位查找改为优先级数组(先到先得) - glTF 的 UV 本就是左上原点,aiProcess_FlipUVs 会把全部贴图上下 颠倒(法线/MR 分布全反)——按扩展名区分 flip - 材质加载 INFO 日志(贴图槽缺失会静默退化默认纹理,留诊断锚点) --- Engine/src/Renderer/Model.cpp | 46 ++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/Engine/src/Renderer/Model.cpp b/Engine/src/Renderer/Model.cpp index 3a2a2ee..1715da1 100644 --- a/Engine/src/Renderer/Model.cpp +++ b/Engine/src/Renderer/Model.cpp @@ -94,10 +94,24 @@ void Model::LoadModel(const std::string& path) { m_ModelPath = path; + // UV 翻转按格式区分: + // OBJ/FBX —— v 原点在底部,需翻到左上惯例(配合"v=0=图像顶"采样) + // glTF/GLB —— UV 本就是左上原点(v=0=图像顶),翻转会把所有 + // 贴图上下颠倒(法线/MR 全反 = 塑料感元凶) + const std::string lower = [&] { + std::string s = path; + std::transform(s.begin(), s.end(), s.begin(), + [](unsigned char c) { return std::tolower(c); }); + return s; + }(); + const bool isGltf = lower.size() >= 5 && + (lower.rfind(".gltf") == lower.size() - 5 || + lower.rfind(".glb") == lower.size() - 4); + Assimp::Importer importer; const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | - aiProcess_FlipUVs | + (isGltf ? 0 : aiProcess_FlipUVs) | aiProcess_GenSmoothNormals | aiProcess_CalcTangentSpace | // 法线贴图 TBN aiProcess_JoinIdenticalVertices); @@ -236,15 +250,22 @@ Scope Model::ProcessMesh(aiMesh* mesh, const aiScene* scene) const std::filesystem::path modelDir = std::filesystem::path(m_ModelPath).parent_path(); - // glTF 的 metallicRoughness 贴图落在 aiTextureType_UNKNOWN + // glTF2 贴图在 assimp 5.x 的落点:MR 合图 → METALNESS(15)/ + // DIFFUSE_ROUGHNESS(16)(同图双槽);baseColor → BASE_COLOR(12)。 + // 先到先得,数组顺序即优先级 const std::pair slots[] = { - {aiTextureType_DIFFUSE, Material::Albedo}, - {aiTextureType_NORMALS, Material::Normal}, - {aiTextureType_UNKNOWN, Material::MetallicRoughness}, - {aiTextureType_EMISSIVE, Material::Emissive}, + {aiTextureType_DIFFUSE, Material::Albedo}, + {aiTextureType_BASE_COLOR, Material::Albedo}, + {aiTextureType_NORMALS, Material::Normal}, + {aiTextureType_METALNESS, Material::MetallicRoughness}, + {aiTextureType_DIFFUSE_ROUGHNESS, Material::MetallicRoughness}, + {aiTextureType_UNKNOWN, Material::MetallicRoughness}, + {aiTextureType_EMISSIVE, Material::Emissive}, + {aiTextureType_EMISSION_COLOR, Material::Emissive}, }; for (const auto& [type, slot] : slots) { + if (!texPaths[slot].empty()) continue; // 高优先级已命中 aiString path; if (material->GetTexture(type, 0, &path) == AI_SUCCESS && path.length > 0) { @@ -252,6 +273,19 @@ Scope Model::ProcessMesh(aiMesh* mesh, const aiScene* scene) } } + // 材质加载可见性:贴图槽缺失/路径解析错误会静默退化成默认 + // 纹理(金属全没 → 塑料感),这里留下诊断锚点 + ENGINE_INFO("Material '{}': albedo={} normal={} MR={} emissive={}", + material->GetName().C_Str(), + texPaths[Material::Albedo].empty() ? "" + : texPaths[Material::Albedo], + texPaths[Material::Normal].empty() ? "" + : texPaths[Material::Normal], + texPaths[Material::MetallicRoughness].empty() ? "" + : texPaths[Material::MetallicRoughness], + texPaths[Material::Emissive].empty() ? "" + : texPaths[Material::Emissive]); + // PBR 因子(glTF2 材质属性;旧资产无此键 → 默认电介质 0/0.5) ai_real metallic = 0.0f, roughness = 0.5f; material->Get(AI_MATKEY_METALLIC_FACTOR, metallic);