unity – 踩坑记录 – 关于AlphaTest投影烘焙后没有镂空的问题

  • Post author:
  • Post category:其他


这是一篇年前:2021.1.28 些的日志


主要是备忘用

帮美术同学修改完 shader 后

发现烘焙后 alpha test 的 shader 都没有了投影镂空的效果

导致树叶之间的投影 乌黑一大片,然后搜索了一下

还好的是,发现 taecg 老师也在某乎上写过这个问题的处理分享


看了这篇文章就知道:unity黑箱 + 文档不说明有多 e xin:

关于AlphaTest阴影烘焙后消失的问题


处理要点:

  • 主纹理名称必须是”_MainTex”,只有这个名称才会被内部识别到,就像后处理Shader中也需要用到这个名称是一样的道理。
  • Shader中的Queue排序在2450-3999之间,也就是”Queue” = “AlphaTest”或者”Queue” = “Transparent”.
  • RenderType设置为”RenderType” = “Transparent”或者”RenderType” = “TransparentCutout”.

记住要处理:Forwardbase 和 ShadowCaster 两个 shader 的 tag, queue 等

如果我们要重写 ShaderGUI 那么注意处理这两点即可,如下:




References

// jave.lin 2022/08/27 为 SanGuo_PBR_MRA_SSS shader 材质的编辑器重写

using UnityEngine;
using UnityEditor;
using System;
using System.Collections.Generic;

public enum JAVELIN_RenderType
{
    Opaque,
    AlphaTest,
    TransparentWithoutPMA,
    TransparentWithPMA,
    Additive,
    Subtractive,
}

public enum JAVELIN_ShowFaceType
{
    Front,
    Back,
    DoubleSide,
}

public class SanGuo_PBR_MRA_SSS_MAT_GUI : ShaderGUI
{
    static MaterialProperty FindAndRemoveProperty(string propertyName, List<MaterialProperty> propertyList)
    {
        return FindAndRemoveProperty(propertyName, propertyList, true);
    }

    static MaterialProperty FindAndRemoveProperty(string propertyName, List<MaterialProperty> propertyList, bool propertyIsMandatory)
    {
        for (var i = 0; i < propertyList.Count; i++)
            if (propertyList[i] != null && propertyList[i].name == propertyName)
            {
                var property = propertyList[i];
                propertyList.RemoveAt(i);
                return property;
            }

        // We assume all required properties can be found, otherwise something is broken
        if (propertyIsMandatory)
            throw new ArgumentException("Could not find MaterialProperty: '" + propertyName + "', Num properties: " + propertyList.Count);
        return null;
    }

    private static bool IsEnabledKW(string kw, Material target)
    {
        return target.IsKeywordEnabled(kw);
    }

    // jave.lin : 参考:2020.3.37f1 builtin shader StandardParticlesShaderGUI.cs 的 SetupMaterialWithBlendMode 函数
    public static void SettingMatBlendMode(Material material, JAVELIN_RenderType blendMode)
    {
        switch (blendMode)
        {
            case JAVELIN_RenderType.Opaque:
                material.SetOverrideTag("RenderType", "Geometry");
                material.SetInt("_BlendOp", (int)UnityEngine.Rendering.BlendOp.Add);
                material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
                material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
                material.SetInt("_ZWrite", 1);
                material.DisableKeyword("_ALPHATEST_ON");
                material.DisableKeyword("_ALPHABLEND_ON");
                material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                //material.DisableKeyword("_ALPHAMODULATE_ON");
                material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Geometry;
                break;
            case JAVELIN_RenderType.AlphaTest:
                material.SetOverrideTag("RenderType", "TransparentCutout");
                material.SetOverrideTag("Queue", "AlphaTest");
                material.SetInt("_BlendOp", (int)UnityEngine.Rendering.BlendOp.Add);
                material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
                material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
                material.SetInt("_ZWrite", 1);
                material.EnableKeyword("_ALPHATEST_ON");
                material.DisableKeyword("_ALPHABLEND_ON");
                material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                //material.DisableKeyword("_ALPHAMODULATE_ON");
                material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest;
                break;
            case JAVELIN_RenderType.TransparentWithoutPMA:
                material.SetOverrideTag("RenderType", "Transparent");
                material.SetInt("_BlendOp", (int)UnityEngine.Rendering.BlendOp.Add);
                material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
                material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
                material.SetInt("_ZWrite", 0);
                material.DisableKeyword("_ALPHATEST_ON");
                material.DisableKeyword("_ALPHABLEND_ON");
                material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                //material.DisableKeyword("_ALPHAMODULATE_ON");
                material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
                break;
            case JAVELIN_RenderType.TransparentWithPMA:
                material.SetOverrideTag("RenderType", "Transparent");
                material.SetInt("_BlendOp", (int)UnityEngine.Rendering.BlendOp.Add);
                material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
                material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
                material.SetInt("_ZWrite", 0);
                material.DisableKeyword("_ALPHATEST_ON");
                material.DisableKeyword("_ALPHABLEND_ON");
                material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
                //material.DisableKeyword("_ALPHAMODULATE_ON");
                material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
                break;
            case JAVELIN_RenderType.Additive:
                material.SetOverrideTag("RenderType", "Transparent");
                material.SetInt("_BlendOp", (int)UnityEngine.Rendering.BlendOp.Add);
                material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
                material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.One);
                material.SetInt("_ZWrite", 0);
                material.DisableKeyword("_ALPHATEST_ON");
                material.EnableKeyword("_ALPHABLEND_ON");
                material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                //material.DisableKeyword("_ALPHAMODULATE_ON");
                material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
                break;
            case JAVELIN_RenderType.Subtractive:
                material.SetOverrideTag("RenderType", "Transparent");
                material.SetInt("_BlendOp", (int)UnityEngine.Rendering.BlendOp.ReverseSubtract);
                material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
                material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.One);
                material.SetInt("_ZWrite", 0);
                material.DisableKeyword("_ALPHATEST_ON");
                material.EnableKeyword("_ALPHABLEND_ON");
                material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                //material.DisableKeyword("_ALPHAMODULATE_ON");
                material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
                break;
        }
    }

    public static void SettingMatShowFaceType(Material material, JAVELIN_ShowFaceType showFaceType)
    {
        switch (showFaceType)
        {
            case JAVELIN_ShowFaceType.Front:
                material.SetInt("_Cull", (int)UnityEngine.Rendering.CullMode.Back);
                break;
            case JAVELIN_ShowFaceType.Back:
                material.SetInt("_Cull", (int)UnityEngine.Rendering.CullMode.Front);
                break;
            case JAVELIN_ShowFaceType.DoubleSide:
                material.SetInt("_Cull", (int)UnityEngine.Rendering.CullMode.Off);
                break;
        }
    }

    private MaterialProperty renderTypeProp;
    private MaterialProperty showFaceTypeProp;

    public void FindProperties(MaterialProperty[] props)
    {
        renderTypeProp = FindProperty("_JL_RenderType", props, false);
        showFaceTypeProp = FindProperty("_JL_ShowFaceType", props, false);
    }

    public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
    {
        FindProperties(properties);

        Material targetMat = materialEditor.target as Material;

        List<MaterialProperty> propertyList = new List<MaterialProperty>(properties);

        FindAndRemoveProperty("_Parallax", propertyList, false);
        FindAndRemoveProperty("_ParallaxMap", propertyList, false);
        FindAndRemoveProperty("_DetailMask", propertyList, false);
        FindAndRemoveProperty("_DetailAlbedoMap", propertyList, false);
        FindAndRemoveProperty("_DetailNormalMapScale", propertyList, false);
        FindAndRemoveProperty("_DetailNormalMap", propertyList, false);
        FindAndRemoveProperty("_UVSec", propertyList, false);

        FindAndRemoveProperty("_SpecularHighlights", propertyList, false);
        FindAndRemoveProperty("_GlossyReflections", propertyList, false);
        FindAndRemoveProperty("_ALPHATEST", propertyList, false);
        FindAndRemoveProperty("_ALPHABLEND", propertyList, false);

        FindAndRemoveProperty("_JL_RenderType", propertyList, false);
        FindAndRemoveProperty("_JL_ShowFaceType", propertyList, false);

        FindAndRemoveProperty("_Cull", propertyList, false);
        FindAndRemoveProperty("_ZWrite", propertyList, false);
        FindAndRemoveProperty("_SrcBlend", propertyList, false);
        FindAndRemoveProperty("_DstBlend", propertyList, false);

        // jave.lin : 根据变体开关来控制 材质属性的显示隐藏
        var alphatest_on = IsEnabledKW("_ALPHATEST_ON", targetMat);
        var emission_on = IsEnabledKW("_EMISSION", targetMat);
        //var sss_on = IsEnabledKW("_SSS_ON", targetMat);

        if (!alphatest_on)
        {
            FindAndRemoveProperty("_Cutoff", propertyList, false);
        }
        if (!emission_on)
        {
            FindAndRemoveProperty("_EmissionColor", propertyList, false);
            FindAndRemoveProperty("_EmissionMap", propertyList, false);
        }
        //if (!sss_on)
        //{
        //    FindAndRemoveProperty("_TranslucentDistortion", propertyList, false);
        //    FindAndRemoveProperty("_TranslucentPower", propertyList, false);
        //    FindAndRemoveProperty("_TranslucentScale", propertyList, false);
        //    FindAndRemoveProperty("_TranslucentAmbientScale", propertyList, false);
        //}

        //var srcRenderType = renderTypeProp.floatValue;
        //materialEditor.ShaderProperty(renderTypeProp, "RenderType");
        //var newRenderType = renderTypeProp.floatValue;
        //if (srcRenderType != newRenderType)
        //{
        //    renderTypeProp.floatValue = (int)newRenderType;
        //    materialEditor.RegisterPropertyChangeUndo("renderType");
        //    materialEditor.PropertiesChanged();
        //}

        // jave.lin : render type
        {
            var src_val = (JAVELIN_RenderType)((int)renderTypeProp.floatValue);
            var new_val = (JAVELIN_RenderType)EditorGUILayout.EnumPopup("RenderType", src_val, GUILayout.ExpandWidth(true));
            if (src_val != new_val)
            {
                renderTypeProp.floatValue = (int)new_val;
                SettingMatBlendMode(targetMat, new_val);
            }
        }

        // jave.lin : show face type
        {
            var src_val = (JAVELIN_ShowFaceType)((int)showFaceTypeProp.floatValue);
            var new_val = (JAVELIN_ShowFaceType)EditorGUILayout.EnumPopup("ShowFaceType", src_val, GUILayout.ExpandWidth(true));
            if (src_val != new_val)
            {
                showFaceTypeProp.floatValue = (int)new_val;
                SettingMatShowFaceType(targetMat, new_val);
            }
        }

        if (propertyList.Count > 0)
        {
            for (int i = 0; i < propertyList.Count; i++)
            {
                materialEditor.ShaderProperty(propertyList[i], propertyList[i].displayName);
            }
        }

        materialEditor.RenderQueueField();
    }
}

注意

在这里插入图片描述



版权声明:本文为linjf520原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。