Unity 批量替换Shader

有时候我们对某一shader弃用或者更替时都是直接对材质球操作,但是当项目中潜藏了不符合预期的材质shader存在的话,就需要这样一个批量替换的功能。

public class ChangeShader : EditorWindow
{
    [MenuItem("*Tool*/Change Shader")]
    public static void ShowWindow()
    {
        EditorWindow editorWindow = GetWindow(typeof(ChangeShader));
        editorWindow.autoRepaintOnSceneChange = false;
    }

    //当前shader
    public Shader currentShader;
    //目标shader
    public Shader changeShader;
    public HashSet<Material> mat = new HashSet<Material>();

    private void OnGUI()
    {
        currentShader = EditorGUILayout.ObjectField("查找 shader", currentShader, typeof(Shader),false) as Shader;
        changeShader = EditorGUILayout.ObjectField("替换 shader", changeShader, typeof(Shader), false) as Shader;
        if (GUILayout.Button("Change"))
        {
            Change();
        }

        if (mat.Count > 0)
        {
        //界面中显示被替换的材质球
            EditorGUILayout.LabelField("替换掉的材质:");
            foreach (var material in mat)
            {
                if (material != null)
                    EditorGUILayout.ObjectField(material, typeof(Material), false);
            }

            if (GUILayout.Button("Clear"))
                mat.Clear();
        }
    }

    public void Change()
    {
        mat.Clear();
        // 加载的路径需要加后缀名
        if (currentShader == null || changeShader == null)
        {
            return;
        }

        var allfiles = Directory.GetFiles("Assets/", "*.mat", SearchOption.AllDirectories);
        var length = allfiles.Length;
        var count = 0;
        for (var i = 0; i < length; i++)
        {
            var file = allfiles[i];
            //显示替换进度
            if (EditorUtility.DisplayCancelableProgressBar("Changing", file, i / (float) length))
            {
                break;
            }
			//根据地址读取材质球
            Material tempMat = AssetDatabase.LoadAssetAtPath<Material>(file);
            if (tempMat.shader == currentShader)
            {
                tempMat.shader = changeShader;
                mat.Add(tempMat);
                // Debug.Log($"Change {tempMat.name} from {currentShader.name} to {changeShader.name}");
                count++;
            }
        }

        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
        EditorUtility.ClearProgressBar();
        EditorUtility.DisplayDialog("一共修改:" + count + "个材质", "就绪", "OK");
    }
}
### 将 Unity 内置渲染管线 Shader 迁移至 URP #### 项目材料升级 为了使现有项目兼容 Universal Render Pipeline (URP),需先通过 Edit->Render Pipeline->Universal Render Pipeline 菜单选项,执行项目的材质文件更新到 URP 材质[^1]。 #### 使用转换工具 对于希望批量处理多个着色器的情况,可通过 Window -> Rendering -> Render Pipeline Convert 功能来实现自动化迁移过程[^2]。此功能会尝试自动调整内置管线下的 HLSL 或 CG 文件结构以适应新的渲染路径需求。 #### PBR 光照模型适配 由于 URP 实现了混合型(前向加延迟)渲染模式,在单一 pass 中完成全部光源计算工作;因此当移植基于物理属性的表面着色程序时,应特别关注 `LitForwardPass.hlsl` 文件内的具体实现细节[^3]: ```hlsl // 示例:简化版PBR光照函数片段 float3 Diffuse = diffuseColor * NdotL; float3 Specular = specularTerm * F * G * D / max(NdotV * NdotL, 0.001); SurfaceData surf; surf.Albedo = albedoTexture.Sample(samplerAlbedoTexture, IN.uv).rgb; surf.Specular = metallicWorkflow ? lerp(0.08 * fresnelSchlickRoughness, specColor.rgb, metalness) : specColor.rgb; surf.NormalWS = normalize(IN.TangentToWorld[0].xyz * surf.NormalTS.x + IN.TangentToWorld[1].xyz * surf.NormalTS.y + IN.TangentToWorld[2].xyz * surf.NormalTS.z); ``` 上述代码展示了如何定义并应用漫反射项与镜面高光项,并考虑到了金属粗糙度工作流的选择性支持。 #### 切换渲染管线资产 在运行期间动态改变使用的渲染管道配置可以通过修改 `GraphicsSettings.renderPipelineAsset` 属性达成。下面给出了一段用于临时替换当前设置为指定 URP 配置实例的小例子[^4]: ```csharp using UnityEngine; public class SwitchURPPipeline : MonoBehaviour { public RenderPipelineAsset URPAsset; private RenderPipelineAsset m_OriUrpAsset; void Modify() { m_OriUrpAsset = GraphicsSettings.renderPipelineAsset; GraphicsSettings.renderPipelineAsset = URPAsset; } void Reset() { GraphicsSettings.renderPipelineAsset = m_OriUrpAsset; m_OriUrpAsset = null; } } ``` 这段脚本允许开发者方便地测试不同版本间的视觉差异效果而无需重启编辑器环境。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值