如何使用Assimp加载透明材质并获取正确的alpha透明度值
问题描述
我搭建了一个包含1面透明墙体、2个立方体的简单测试场景。
该透明墙体在Blender中设置的基础色参数为:RGBA = {0.8, 0.2, 0.6, 0.3}
我将场景导出为gltf格式后,使用Assimp完成模型加载。
我编写的材质提取代码如下(代码较为零散,是我为排查问题反复调试修改的版本):
void ExtractMaterial(const aiScene* scene) { std::unordered_map<std::string, std::string> customProperties; if (scene->HasMaterials()) { for (uint32_t i = 0; i < scene->mNumMaterials; i++) { auto aiMaterial = scene->mMaterials[i]; auto aiMaterialName = aiMaterial->GetName(); aiColor4D aiColor; if (aiMaterial->Get(AI_MATKEY_COLOR_DIFFUSE, aiColor) == AI_SUCCESS) { std::cout << std::endl; } float opacity = 1.0f; if (aiMaterial->Get(AI_MATKEY_OPACITY, opacity) == AI_SUCCESS) { std::cout << std::endl; } float transFac = 1.0f; if (aiMaterial->Get(AI_MATKEY_TRANSPARENCYFACTOR, transFac) == AI_SUCCESS) { std::cout << std::endl; } float transCol = 1.0f; if (aiMaterial->Get(AI_MATKEY_COLOR_TRANSPARENT, transCol) == AI_SUCCESS) { std::cout << std::endl; } for (int p = 0; p < aiMaterial->mNumProperties; p++) { aiMaterialProperty* pt = aiMaterial->mProperties[p]; switch (pt->mType) { case aiPTI_String: { const char* data = pt->mData; customProperties[pt->mKey.C_Str()] = data; } break; case aiPTI_Float: { std::stringstream ss; ss << *(float*)pt->mData; customProperties[pt->mKey.C_Str()] = ss.str(); if (strcmp(pt->mKey.C_Str(), "$mat.opacity") == 0) { float num = *(float*)pt->mData; if (num != 1.0) { std::cout << std::endl; } } else if (strcmp(pt->mKey.C_Str(), "$mat.gltf.alphaMode") == 0) { float mode = *(float*)pt->mData; std::cout << std::endl; } } break; } } } } }
我在所有包含std::cout << std::endl;语句的位置设置了断点,添加该语句的作用是确保调试器会在对应代码位置中断。
调试结果显示,墙体材质读取得到的aiColor4D aiColor参数中,RGB值与Blender中设置的数值完全一致,但alpha通道值为1.0f,与预期的0.3f不符。
我额外读取了opacity、transFac、transCol变量,同时遍历customProperties映射表查找存储真实alpha值的字段,均未找到目标数值。
由于Windows 10系统默认的3D网格查看器可以正常显示该模型的透明效果,可确认材质导出环节无异常,现咨询如何正确读取该墙体材质的alpha值。
解决方案
这个问题是Assimp加载glTF材质的映射逻辑导致的,按下面的步骤排查修复即可:
- 先确认Assimp版本:5.0及更早的旧版本对glTF PBR材质的映射有缺陷,不会自动把
baseColorFactor的alpha值同步到AI_MATKEY_COLOR_DIFFUSE的A通道,也不会自动赋值给AI_MATKEY_OPACITY字段,这是读不到值的核心原因。 - 之前遍历自定义属性的逻辑有漏洞:真实的alpha值存在
$mat.gltf.pbrMetallicRoughness.baseColorFactor这个4维浮点数组属性里,之前处理aiPTI_Float类型时默认按单个float解析,自然拿不到完整的4通道颜色值。 - 直接读取这个glTF专属字段就能拿到正确的alpha,参考代码:
aiColor4D gltfBaseColor; if (aiMaterial->Get("$mat.gltf.pbrMetallicRoughness.baseColorFactor", 0, 0, gltfBaseColor) == AI_SUCCESS) { float alpha = gltfBaseColor.a; // 这里就能取到Blender中设置的0.3f }
- 如果升级到Assimp 5.2及以上版本,只要导入时不开启会篡改材质数据的后处理选项,
AI_MATKEY_COLOR_DIFFUSE的alpha通道会被自动正确填充,不需要额外读取glTF专属字段。 - 顺带提一句,之前读不到
$mat.gltf.alphaMode是因为这个属性是字符串类型,不是float类型,之前只在字符串分支做了通用存储没有单独解析,它的正确值应该是"BLEND",对应透明混合模式。
内容的提问来源于stack exchange,提问作者BrodaJarek3
相关产品推荐
相关产品推荐

