GameTech/URP 渲染实战

案例 13.3批量检查贴图导入设置入门

目标:写一个编辑器菜单,按命名约定检查贴图的 sRGB 和 Normal Map 设置,并检查材质的法线槽里是否放了非法线贴图。

13.2 和 13.5 节的错误有一个共同点:它们都可以通过检查导入设置在“进场景之前”发现。前提是项目有统一的命名约定,例如颜色贴图以 _albedo、_basecolor 结尾,数据贴图以 _mask、_roughness 结尾,法线贴图以 _normal 结尾。

Assets/Cookbook/Ch13/Editor/PBRTextureAudit.cs(节选:rules)
// 后缀 -> 期望:颜色类贴图开 sRGB;数据类贴图关 sRGB;法线贴图必须是 Normal Map 类型
static readonly string[] ColorSuffix = { "_albedo", "_basecolor", "_diffuse", "_color", "_emission" };
static readonly string[] DataSuffix  = { "_mask", "_metallic", "_roughness", "_smoothness", "_ao", "_occlusion", "_height" };
static readonly string[] NormalSuffix = { "_normal", "_nrm", "_n" };

public static List<string> AuditFolder(string folder)
{
    var issues = new List<string>();
    foreach (var guid in AssetDatabase.FindAssets("t:Texture2D", new[] { folder }))
    {
        string path = AssetDatabase.GUIDToAssetPath(guid);
        if (!(AssetImporter.GetAtPath(path) is TextureImporter ti)) continue;
        string n = System.IO.Path.GetFileNameWithoutExtension(path).ToLowerInvariant();

        if (NormalSuffix.Any(n.EndsWith))
        {
            if (ti.textureType != TextureImporterType.NormalMap)
                issues.Add($"{path}: 名字是法线贴图,但 Texture Type 不是 Normal Map(会被当颜色做 sRGB 解码,也不会按法线格式压缩)");
        }
        else if (DataSuffix.Any(n.EndsWith))
        {
            if (ti.sRGBTexture)
                issues.Add($"{path}: 数据贴图开启了 sRGB,金属度/光滑度/AO 会被错误地“解码变暗”");
        }
        else if (ColorSuffix.Any(n.EndsWith))
        {
            if (!ti.sRGBTexture)
                issues.Add($"{path}: 颜色贴图关闭了 sRGB,颜色会显得发灰、偏亮");
        }
    }
    return issues;
}

// 材质的法线槽里放了非 Normal Map 类型的贴图(Inspector 会提示 Fix Now,但批量导入的材质常被忽略)
public static List<string> AuditMaterials(string folder)
{
    var issues = new List<string>();
    foreach (var guid in AssetDatabase.FindAssets("t:Material", new[] { folder }))
    {
        var mat = AssetDatabase.LoadAssetAtPath<Material>(AssetDatabase.GUIDToAssetPath(guid));
        foreach (var prop in new[] { "_BumpMap", "_DetailNormalMap" })
        {
            if (!mat.HasProperty(prop) || !(mat.GetTexture(prop) is Texture2D tex)) continue;
            if (AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(tex)) is TextureImporter ti && ti.textureType != TextureImporterType.NormalMap)
                issues.Add($"{mat.name}.{prop} = {tex.name}: 贴图不是 Normal Map 类型");
        }
    }
    return issues;
}

菜单 Cookbook › Ch13 › Audit PBR Textures 会检查 Project 窗口中选中的文件夹(未选中时检查整个 Assets),把问题输出为警告。工具只报告、不自动修改,因为导入设置的改动会触发重新导入,并可能改变已经调好的外观,应当由人确认。配图脚本在拍摄砖墙配图时对配套贴图目录运行了一次,结果为零个问题——这是因为配套工程用 AssetPostprocessor 在导入时就自动设好了。两者配合使用效果最好:AssetPostprocessor 保证新导入的贴图正确,检查工具负责找出历史遗留和被手动改错的贴图。