UnityShader复合材质(包含shader材质编辑器编写)

这篇博客详细介绍了如何在Unity中创建一个自定义的Shader GUI,包括绘制主要和次要贴图,金属源选择,平滑度控制,法线贴图和发射贴图等功能。通过使用ShaderGUI类,可以实现材质编辑器中的高级用户界面,允许开发者更直观地调整Shader参数。
摘要由CSDN通过智能技术生成

自定义材质GUI,注释都有

#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;

public class MyLightShaderGUI : ShaderGUI
{
    /// <summary>
    /// 平滑源
    /// </summary>
    enum SmoothnessSource
    {
        Uniform, Albedo, Metallic
    }
    
    private Material _target;
    private MaterialEditor _materialEditor;
    private MaterialProperty[] _properties;
    
    public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
    {
        //base.OnGUI(materialEditor, properties);
        _target = materialEditor.target as Material;
        _materialEditor = materialEditor;
        _properties = properties;
        DrawMain();
        DrawSecondary();
    }

    void DrawMain()
    {
        GUILayout.Label("主要贴图", EditorStyles.boldLabel);
        //画出主贴图挂件
        MaterialProperty mainTex = SelfFindProperty("_MainTex"); //主贴图属性
        _materialEditor.TexturePropertySingleLine(
            MakeLabel(mainTex,"主贴图(RGB)"),
            mainTex,
            SelfFindProperty("_Tint")); //生成挂件, 并在同一行生成颜色选择器
        DrawMetallic();
        DrawSmoothness();
        DrawNorml();
        DrawEmission();
        _materialEditor.TextureScaleOffsetProperty(mainTex); //创建纹理缩放偏移ST
    }

    /// <summary>
    /// 次要项
    /// </summary>
    void DrawSecondary() 
    {
        GUILayout.Label("次要贴图", EditorStyles.boldLabel);

        MaterialProperty detailTex = SelfFindProperty("_DetailTex");
        _materialEditor.TexturePropertySingleLine(
            MakeLabel(detailTex, "Albedo (RGB) multiplied by 2"), detailTex
        );

        DrawSecondaryNormal();
        _materialEditor.TextureScaleOffsetProperty(detailTex);
    }
    
    void DrawSecondaryNormal() 
    {
        MaterialProperty detailNormalTex = SelfFindProperty("_DetailNormalMap");
        _materialEditor.TexturePropertySingleLine(
            MakeLabel(detailNormalTex),
            detailNormalTex,
            detailNormalTex.textureValue ? SelfFindProperty("_DetailBumpScale") : null);
    }

    void DrawSmoothness()
    {
        //根据是否启用关键字设置金属源
        SmoothnessSource source = SmoothnessSource.Uniform;
        if (IsKeywordEnabled("_SMOOTHNESS_ALBEDO")) {
            source = SmoothnessSource.Albedo;
        }
        else if (IsKeywordEnabled("_SMOOTHNESS_METALLIC")) {
            source = SmoothnessSource.Metallic;
        }
        
        MaterialProperty smoothness = SelfFindProperty("_Smoothness");
        EditorGUI.indentLevel += 2; //缩进级别+2
        _materialEditor.ShaderProperty(smoothness, MakeLabel(smoothness));
        EditorGUI.indentLevel += 1;
        EditorGUI.BeginChangeCheck();
        RecordAction("Smothness Source"); //支持回撤功能,必须在修改之前
        source = (SmoothnessSource)EditorGUILayout.EnumPopup(MakeLabel("金属Source"), source); //枚举
        if (EditorGUI.EndChangeCheck())
        {
            //如果修改了, 那么设置关键字
            SetKeyword("_SMOOTHNESS_ALBEDO", source == SmoothnessSource.Albedo);
            SetKeyword("_SMOOTHNESS_METALLIC", source == SmoothnessSource.Metallic);
        }
        EditorGUI.indentLevel -= 3;
    }

    void DrawMetallic()
    {
        MaterialProperty metallicMap = SelfFindProperty("_MetallicMap");
        EditorGUI.BeginChangeCheck(); //当发生改变才执行此操作
        _materialEditor.TexturePropertySingleLine(
            MakeLabel(metallicMap),
            metallicMap,
            //使用金属贴图时隐藏滑块
            metallicMap.textureValue?null:SelfFindProperty("_Metallic")
        );
        if (EditorGUI.EndChangeCheck())
        {
            SetKeyword("_METALLIC_MAP", metallicMap.textureValue);
        }
    }

    void DrawNorml()
    {
        MaterialProperty normalTex = SelfFindProperty("_NormalMap");
        _materialEditor.TexturePropertySingleLine(
            MakeLabel(normalTex),
            normalTex,
            //当没有法线贴图将不会显示 缩放比例
            normalTex.textureValue ? SelfFindProperty("_BumpScale") : null); //生成挂件, 并在同一行生成颜色选择器
    }

    //0~99用于亮度 0~3用于曝光
    static ColorPickerHDRConfig emissionConfig =
        new ColorPickerHDRConfig(0f, 99f, 1f / 99f, 3f);
    void DrawEmission()
    {
        MaterialProperty map = SelfFindProperty("_EmissionMap");
        EditorGUI.BeginChangeCheck();
        _materialEditor.TexturePropertyWithHDRColor(
            MakeLabel(map, "Emission (RGB)"),
            map,
            SelfFindProperty("_Emission"),
            emissionConfig,
            false
            
        );
        if (EditorGUI.EndChangeCheck())
        {
            SetKeyword("_EMISSION_MAP", map.textureValue);
        }
    }


    MaterialProperty SelfFindProperty(string property)
    {
        return FindProperty(property, _properties);
    }
    
    static GUIContent staticLabel = new GUIContent();
    
    static GUIContent MakeLabel (
        MaterialProperty property, string tooltip = null
    ) {
        staticLabel.text = property.displayName;
        staticLabel.tooltip = tooltip;
        return staticLabel;
    }
    
    static GUIContent MakeLabel (string tooltip = null
    ) {
        staticLabel.tooltip = tooltip;
        return staticLabel;
    }

    /// <summary>
    /// 设置关键字,所设置的关键字,可以在shader文件中定义多编译的指令
    /// </summary>
    void SetKeyword(string keyword, bool state)
    {
        if(state)
            _target.EnableKeyword(keyword);
        else
            _target.DisableKeyword(keyword);
    }
    
    /// <summary>
    /// 是否开启了关键字
    /// </summary>
    bool IsKeywordEnabled (string keyword) {
        return _target.IsKeywordEnabled(keyword);
    }
    
    /// <summary>
    /// 使得支持撤销操作,使用时必须在改变前使用
    /// </summary>
    /// <param name="label"></param>
    void RecordAction (string label) {
        _materialEditor.RegisterPropertyChangeUndo(label);
    }
}
#endif

My First Lighting Shader文件

#pragma shader_feature 这个指令如果没有使用到这个关键字比如没有创建金属贴图就不会编译这个变体
#pragma shader_feature _ _METALLIC_MAP //自定义金属贴图关键字
#pragma shader_feature _ _SMOOTHNESS_ALBEDO _SMOOTHNESS_METALLIC //自定义金属源关键字
#pragma shader_feature _EMISSION_MAP //这里发射自发光只在basePass中有

相应的shader文件 My_Lighting.cginc

float GetMetallic(Interpolators i)
{
    #if defined(_METALLIC_MAP)
        return tex2D(_MetallicMap, i.uv.xy).r;
    #else
        return _Metallic;
    #endif
}

float GetSmoothness(Interpolators i)
{
    float smoothness = 1;
    #if defined(_SMOOTHNESS_ALBEDO) //定义从反照率设置平滑度
        smoothness = tex2D(_MainTex, i.uv.xy).a;//DXT5中x存储在alpha通道中
    #elif defined(_SMOOTHNESS_METALLIC) && defined(_MetallicMap)
        //设置了金属贴图 并且 开启了以金属贴图为金属源
        smoothness = tex2D(_MetallicMap, i.uv.xy).a;
    #endif
    return smoothness * _Smoothness;
}

float3 GetEmission(Interpolators i)
{
    #if defined(FORWARD_BASE_PASS)
        #if defined(_EMISSION_MAP)
            return tex2D(_EmissionMap, i.uv.xy) * _Emission;
        #else
            return _Emission;
        #endif
    #else
        return 0;
    #endif
}
片元程序中
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值