• 设置Unity URP管线中的渲染开关


    在上一节中,我们添加了外轮廓线,但这个外轮廓线在所有使用该Shader的网格上是始终存在的。

    如果我们想做一个开关,决定是否打开外轮廓线时,我们可以使用一个新的Uniform bool值,然后判断bool是否为true来开启外轮廓线。

    但是这样会造成性能的浪费,因为就算我们没有开启这个功能,Shader还是会遍历每一个if条件。这与GPU的运行原理有关。
    故我们使用Unity的多编译功能,将Shader多次编译成多个子Shader。

    Shader中添加开关

    定义开关名称

    // 自定义关键字
    [Toggle(_ENABLE_OUTLINE_ON)] _EnableOutline("Enable OutLine", Float) = 0.0
    // 默认关键字(默认为 名称大写+_ON)
    [Toggle] _EnableOutline("Enable OutLine", Float) = 0.0
    // 默认关键字为(_ENABLEOUTLINE_ON)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在Input中声明变量

    1.
    half _EnableInline;
    
    2.
    #ifdef UNITY_DOTS_INSTANCING_ENABLED
    UNITY_DOTS_INSTANCING_START(MaterialPropertyMetadata)
    	...
    	UNITY_DOTS_INSTANCED_PROP(float , _EnableInline)
    UNITY_DOTS_INSTANCING_END(MaterialPropertyMetadata)
    
    3.
    #define _EnableInline           UNITY_ACCESS_DOTS_INSTANCED_PROP_FROM_MACRO(float  , Metadata__EnableInline)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    定义关键字

    //pass中定义
    #progma shader_feature _ENABLE_OUTLINE_ON//自定义关键字
    #progma shader_feature _ENABLEOUTLINE_ON//默认关键字
    
    • 1
    • 2
    • 3

    使用关键字

    #if defined(_ENABLE_OUTLINE_ON)
    
    #else
    
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在GUI中设置开关,来控制该关键字

    在子GUI面板中添加按钮设置Shader中变量值

    public static class Styles
    {
        public static readonly GUIContent InlineEnable = new GUIContent("开启内勾边",
            "");
    }
    
    public struct LitProperties
    {
        public MaterialProperty InlineEnabled;
        
        public LitProperties(MaterialProperty[] properties)
        {
            InlineEnabled = BaseShaderGUI.FindProperty("_EnableInline", properties, false);
        }
    }
    
    /// 
    /// 当滚轮滑动材质Inspector面板时,该函数调用4+次
    /// 当修改参数或点击按钮时,该函数也会调用约8-12次
    /// 因此可将该函数看作多次遍历的函数
    /// 
    public static void DoDetailArea(LitProperties properties, MaterialEditor materialEditor)
    {
        materialEditor.ColorProperty(properties.OutLineColor, Styles.OutLineColorContent.text);
        materialEditor.FloatProperty(properties.OutLineSize, Styles.OutLineSizeContent.text);
    
        // 显示按钮,设置GUI按钮的值,返回开关选中的状态
        bool inlineEnabled = EditorGUILayout.Toggle(Styles.InlineEnable, properties.InlineEnabled.floatValue > 0.5f);
        // 根据按钮的选中状态修改Shader值
        properties.InlineEnabled.floatValue = inlineEnabled ? 1f : 0f;
    
        // BeginDisabledGroup参数填True,则为禁用Begin至End直接的功能。在untiy面板上置灰。
        EditorGUI.BeginDisabledGroup(!inlineEnabled);
        {
            materialEditor.FloatProperty(properties.InlineSize, Styles.InlineSizeContent.text);
            materialEditor.FloatProperty(properties.Inlineluminance, Styles.InlineluminanceContent.text);
            materialEditor.FloatProperty(properties.HightLightTransition, Styles.HightLightTransitionContent.text);
        }
        EditorGUI.EndDisabledGroup();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    此时,便可以通过按钮设置properties.InlineEnabled.floatValue的值了。

    根据Shader中变量值,设置宏的值

    根据Shader中变量值"_EnableInline",设置宏"_ENABLE_INLINE_ON"的值

    public static void SetMaterialKeywords(Material material)
    {
        if (material.HasProperty("_EnableInline"))
        {
            bool isSnowEnabled = material.GetFloat("_EnableInline") > 0.5f;
            CoreUtils.SetKeyword(material, "_ENABLE_INLINE_ON", isSnowEnabled);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    当用户使用这个ShaderGUI将材质加载到内存中或者改变Inspector中的值时,编辑器调用下面这个方法。我们在这个方法中调用SetMaterialKeywords函数

    public override void ValidateMaterial(Material material)
    {
        CP_DragonOutLineGUI.SetMaterialKeywords(material);
    }
    
    • 1
    • 2
    • 3
    • 4

    该方法可用于设置材质中的各个宏定义。

  • 相关阅读:
    和拐友们操作Dockerfile 优化及本地私有仓库搭建
    linux修改最大线程数却未生效的原因
    CleanMyMac X“断网激活”真的可以吗?
    NX二次开发-基于PycharmIDE的NXOpen Python开发环境配置
    【HTML专栏1】语法规范、基础结构标签
    CSS3 2D转换-扭曲、缩放
    SpringBoot怎么自定义一个Starter ?
    Windows terminal美化工具Oh-My-Posh
    【docker】dockerfile优化镜像大小
    详解K8S入口Ingerss
  • 原文地址:https://blog.csdn.net/weixin_44518102/article/details/133943635