• 设置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

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

  • 相关阅读:
    selenium + robotframework的运行原理
    记账时,花费如何按类别分类
    windows下安装部署 hadoop
    大环境之下软件测试行业趋势能否上升?
    新来个技术总监,把Redis高可用讲的那叫一个明白,YYDS
    设计模式之解释器模式
    【MATLAB源码-第82期】基于matlab的OFDM系统载波频移偏差(CFO)估计,对比三种不同的方法。
    电脑文件夹莫名其妙消失?不用担心,6招教你轻松找回
    Codeforces Round #814 (Div. 2) A.B.C
    Zabbix之部署代理服务器
  • 原文地址:https://blog.csdn.net/weixin_44518102/article/details/133943635