Improve PBR quality: mip chains, anisotropic filtering, baseColorFactor

Root causes behind blurry/unphysical materials (4K pocket watch render
mushy, glass fully opaque, watch hands unreadable):

- Textures loaded via stbi had a single mip level: 4096x4096 albedo/MR
  maps sampled with no LOD -> minification aliasing turned fine detail
  (watch hands) into noise. Generate a full blit-based mip chain with
  per-level layout transitions.
- samplerAnisotropy was never enabled on the device and every sampler
  was created with anisotropy disabled: grazing-angle surfaces (watch
  face, ground) collapsed into a blur. Enable the device feature and
  16x anisotropic filtering on material texture samplers.
- glTF baseColorFactor was ignored: the glass material (alphaMode
  BLEND, no baseColor texture, baseColorFactor.a = 0.3) fell back to
  the default white texture with alpha = 1 and rendered fully opaque.
  MaterialParams gains a baseColor vec4 (rgb tints albedo, a scales
  the blend alpha) threaded through both PBR shaders.
- alphaMode MASK was treated as opaque: add a factors.w switch that
  performs an alpha cutout test in the opaque shader.
- Fix material cache key dropping factors.z (separate-roughness
  switch); it now encodes the full factors and baseColor vectors.
This commit is contained in:
2026-10-05 12:01:07 +08:00
parent a3037cd401
commit 5d88ed2057
9 changed files with 124 additions and 23 deletions
+18 -3
View File
@@ -695,12 +695,27 @@ ParsedMesh Model::ProcessMesh(const aiMesh* mesh, const aiScene* scene,
params.factors = glm::vec4(static_cast<f32>(metallic),
static_cast<f32>(roughness), 0.0f, 0.0f);
// glTF alphaMode:BLEND = 半透明(透明绘制队列 + 深度只测不写)。
// MASK(alpha cutout)暂按不透明——需要 alpha test,后续演进。
// baseColorFactor:rgb 调色进 albedo;a 是 BLEND 材质的透明度
//(玻璃等无 baseColor 贴图、纯靠 factor alpha 的材质全靠它,
// 缺了会退化成兜底白纹理的 a=1 = 完全不透)
aiColor4D baseColor(1.0f, 1.0f, 1.0f, 1.0f);
if (material->Get(AI_MATKEY_BASE_COLOR, baseColor) == AI_SUCCESS) {
params.baseColor = glm::vec4(baseColor.r, baseColor.g,
baseColor.b, baseColor.a);
}
// glTF alphaMode:
// BLEND = 半透明(透明绘制队列 + 深度只测不写)
// MASK = 镂空(factors.w=1 → shader 侧 alpha test 丢弃,
// 表针/栅栏等硬边贴图常见)仍走不透明队列
// OBJ/FBX 无此键 → 恒不透明(资产格式定义写死)
aiString alphaMode;
if (material->Get(AI_MATKEY_GLTF_ALPHAMODE, alphaMode) == AI_SUCCESS) {
out.transparent = (alphaMode == aiString("BLEND"));
if (alphaMode == aiString("BLEND")) {
out.transparent = true;
} else if (alphaMode == aiString("MASK")) {
params.factors.w = 1.0f;
}
}
} else {
// FBX/OBJ 独立贴图工作流