在URP管线中添加ShaderMaterial自定义GUI的方法

编写GUI面板

1. 新建GUI子面板

using UnityEngine;
using UnityEngine.Rendering;

namespace UnityEditor.Rendering.Universal.ShaderGUI
{
    internal class CP_XXXOutLineGUI
    {
        public static class Styles{}

        public struct LitProperties
        {
            public LitProperties(MaterialProperty[] properties){}
        }
        public static void DoDetailArea(LitProperties properties, MaterialEditor materialEditor){}
        public static void SetMaterialKeywords(Material material){}
    }
}

2. 将在Shader关联的GUI面板中注册该子面板

internal class CP_XXXLitShader : BaseShaderGUI
{
	//声明子面板属性
    private CP_XXXOutLineGUI.LitProperties litXXXOutLineProperties;


    public override void FillAdditionalFoldouts(MaterialHeaderScopeList materialScopesList)
    {
  		
    }
  	public override void FindProperties(MaterialProperty[] properties)
    {
        base.FindProperties(properties);
        // 新建子面板属性
        litXXXOutLineProperties = new CP_XXXOutLineGUI.LitProperties(properties);
    }
}

3. 注册列表头部展开区域

FillAdditionalFoldouts(MaterialHeaderScopeList)会在继承BaseShaderGUI的类中由系统自动调用,它传入当前材质GUI的列表实例,我们通过RegisterHeaderScope可以添加新的列表项目。

public override void FillAdditionalFoldouts(MaterialHeaderScopeList materialScopesList)
{
	materialScopesList.RegisterHeaderScope(LitDetailGUI.Styles.detailInputs, Expandable.Details, _ => LitDetailGUI.DoDetailArea(litDetailProperties, materialEditor));
}

注册函数:materialScopesList.RegisterHeaderScope<TEnum>(GUIContent, TEnum, Action<Material>)
在这里插入图片描述

(1)创建头部列表GUIContext对象

public GUIContent(...);
- string text	文本
- Texture image	图片
- string tooltip 鼠标指针当前悬停在其上或具有键盘焦点的控件的工具提示。
internal class CP_XXXOutLineGUI{
	public static class Styles
	{
	     public static readonly GUIContent OutLineInputs = new GUIContent("Outline Inputs",
	        "This Let You Open The OutLine Panel");
	}
}

(2)设置掩码

掩码设置要求,掩码按照位来设置,每个掩码占一个位字节。
如:在URP内置代码BaseShaderGUI:ShaderGUI类中已经设置了部分掩码

[URPHelpURL("shaders-in-universalrp")]
protected enum Expandable
{
    SurfaceOptions = 1 << 0,
    SurfaceInputs = 1 << 1,
    Advanced = 1 << 2,
    Details = 1 << 3,
}

其中SurfaceOptions、SurfaceInputs、Advanced 都已被系统注册,在URPShader的LitShader(其他Shader中可能也有)中,Details也在重写函数FillAdditionalFoldouts中被注册

materialScopesList.RegisterHeaderScope(
	LitDetailGUI.Styles.detailInputs, 
	Expandable.Details, 
	_ => LitDetailGUI.DoDetailArea(litDetailProperties, materialEditor)
);

我们仿照URP标准库中的写法,添加自定义掩码的扩展

在CP_XXXLitShader中自定义
protected enum AdditionalExpandable
{
	...其他掩码(163264128256)
	OutlineMask = 512,
}

(3) 注册列表头部区域

public override void FillAdditionalFoldouts(MaterialHeaderScopeList materialScopesList)
{
    materialScopesList.RegisterHeaderScope(
    	CP_XXXOutLineGUI.Styles.OutLineInputs, 
    	AdditionalExpandable.OutlineMask, 
    	_ => CP_XXXOutLineGUI.DoDetailArea(litXXXOutLineProperties, materialEditor));
}

现在返回Unity,查看Shader列表。发现已经有了列表头显示。
在这里插入图片描述

4. 添加属性列表的显示

首先OutLine需要的参数有OutLineColor和OutLineSize。
首先在LitProperties中声明该属性,并绑定该属性的Shader名称。

public struct LitProperties
{
    public MaterialProperty OutLineColor;
    public MaterialProperty OutLineSize;


    public LitProperties(MaterialProperty[] properties)
    {
        OutLineColor = BaseShaderGUI.FindProperty("_OutlineColor", properties, false);//false-->未找到不抛出异常
        OutLineSize  = BaseShaderGUI.FindProperty("_OutlineSize", properties, false); 
    }
}

当展开OutLine下拉框时:调用public static void DoDetailArea(LitProperties properties, MaterialEditor materialEditor)函数

public static void DoDetailArea(LitProperties properties, MaterialEditor materialEditor)
{
    materialEditor.ColorProperty(properties.OutLineColor, Styles.OutLineColorContent.text);
    materialEditor.FloatProperty(properties.OutLineSize, Styles.OutLineSizeContent.text);
}

在这里插入图片描述
展开显示
在这里插入图片描述
修改属性,Shader中参数被修改。

其他类型

// 按钮类型
bool depthFadeEnabled = EditorGUILayout.Toggle(Styles.depthFadeEnabledText, properties.depthFadeEnabled.floatValue > 0.5f);
properties.depthFadeEnabled.floatValue = depthFadeEnabled ? 1.0f : 0.0f;

//滑轮类型
properties.depthFadeDist.floatValue = 
	EditorGUILayout.Slider(Styles.depthFadeDistText, properties.depthFadeDist.floatValue, 0.01f, 10.0f);

其他参照Unity官方文档
https://docs.unity.cn/cn/2019.4/ScriptReference/EditorGUILayout.html

整体架构

using System;
using UnityEngine;
using UnityEditor;

namespace UnityEditor.Rendering.Universal.ShaderGUI
{

    internal class CP_DragonLitShader : BaseShaderGUI
    {
        protected enum AdditionalExpandable
        {
            SnowInputs = 16,
            DepthFadeInputs = 32,
            。。。
        }


        private LitGUI.LitProperties litProperties;
        private CP_LitDetailGUI.LitProperties litDetailProperties;
        private CP_SnowGUI.LitProperties litSnowProperties;
       。。。


        public override void FillAdditionalFoldouts(MaterialHeaderScopeList materialScopesList)
        {
            materialScopesList.RegisterHeaderScope(CP_LitDetailGUI.Styles.detailInputs, Expandable.Details, _ => CP_LitDetailGUI.DoDetailArea(litDetailProperties, materialEditor));
            materialScopesList.RegisterHeaderScope(CP_DragonColorGUI.Styles.inputs, AdditionalExpandable.DragonColorInputs, _ => CP_DragonColorGUI.DoDetailArea(litDragonColorProperties, materialEditor));
            materialScopesList.RegisterHeaderScope(CP_SnowGUI.Styles.snowInputs, AdditionalExpandable.SnowInputs, _ => CP_SnowGUI.DoDetailArea(litSnowProperties, materialEditor));
            。。。

        }

        // collect properties from the material properties
        public override void FindProperties(MaterialProperty[] properties)
        {
            base.FindProperties(properties);
            litProperties = new LitGUI.LitProperties(properties);
            litDetailProperties = new CP_LitDetailGUI.LitProperties(properties);
            litDragonColorProperties = new CP_DragonColorGUI.LitProperties(properties);
            litSnowProperties = new CP_SnowGUI.LitProperties(properties);
            。。。
        }

        // material changed check
        public override void ValidateMaterial(Material material)
        {
            SetMaterialKeywords(material, LitGUI.SetMaterialKeywords, CP_LitDetailGUI.SetMaterialKeywords);
            CP_SnowGUI.SetMaterialKeywords(material);
           。。。
        }


        // material main surface options
        public override void DrawSurfaceOptions(Material material)
        {
            if (material == null)
                throw new ArgumentNullException("material");

            // Use default labelWidth
            EditorGUIUtility.labelWidth = 0f;

            // Detect any changes to the material
            EditorGUI.BeginChangeCheck();
            if (litProperties.workflowMode != null)
            {
                DoPopup(LitGUI.Styles.workflowModeText, litProperties.workflowMode, Enum.GetNames(typeof(LitGUI.WorkflowMode)));
            }
            if (EditorGUI.EndChangeCheck())
            {
                foreach (var obj in blendModeProp.targets)
                    MaterialChanged((Material)obj);
            }
            base.DrawSurfaceOptions(material);
        }

        // material main surface inputs
        public override void DrawSurfaceInputs(Material material)
        {
            base.DrawSurfaceInputs(material);
            LitGUI.Inputs(litProperties, materialEditor, material);
            DrawEmissionProperties(material, true);
            DrawTileOffset(materialEditor, baseMapProp);
        }

        // material main advanced options
        public override void DrawAdvancedOptions(Material material)
        {
            if (litProperties.reflections != null && litProperties.highlights != null)
            {
                EditorGUI.BeginChangeCheck();
                materialEditor.ShaderProperty(litProperties.highlights, LitGUI.Styles.highlightsText);
                materialEditor.ShaderProperty(litProperties.reflections, LitGUI.Styles.reflectionsText);
                if (EditorGUI.EndChangeCheck())
                {
                    MaterialChanged(material);
                }
            }

            base.DrawAdvancedOptions(material);
        }

        public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)
        {
            if (material == null)
                throw new ArgumentNullException("material");

            // _Emission property is lost after assigning Standard shader to the material
            // thus transfer it before assigning the new shader
            if (material.HasProperty("_Emission"))
            {
                material.SetColor("_EmissionColor", material.GetColor("_Emission"));
            }

            base.AssignNewShaderToMaterial(material, oldShader, newShader);

            if (oldShader == null || !oldShader.name.Contains("Legacy Shaders/"))
            {
                SetupMaterialBlendMode(material);
                return;
            }

            SurfaceType surfaceType = SurfaceType.Opaque;
            BlendMode blendMode = BlendMode.Alpha;
            if (oldShader.name.Contains("/Transparent/Cutout/"))
            {
                surfaceType = SurfaceType.Opaque;
                material.SetFloat("_AlphaClip", 1);
            }
            else if (oldShader.name.Contains("/Transparent/"))
            {
                // NOTE: legacy shaders did not provide physically based transparency
                // therefore Fade mode
                surfaceType = SurfaceType.Transparent;
                blendMode = BlendMode.Alpha;
            }
            material.SetFloat("_Surface", (float)surfaceType);
            material.SetFloat("_Blend", (float)blendMode);

            if (oldShader.name.Equals("Standard (Specular setup)"))
            {
                material.SetFloat("_WorkflowMode", (float)LitGUI.WorkflowMode.Specular);
                Texture texture = material.GetTexture("_SpecGlossMap");
                if (texture != null)
                    material.SetTexture("_MetallicSpecGlossMap", texture);
            }
            else
            {
                material.SetFloat("_WorkflowMode", (float)LitGUI.WorkflowMode.Metallic);
                Texture texture = material.GetTexture("_MetallicGlossMap");
                if (texture != null)
                    material.SetTexture("_MetallicSpecGlossMap", texture);
            }

            MaterialChanged(material);
        }
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Elsa的迷弟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值