Unity模型透明功能(HDRP)

先整理一下原来透明怎么设置的

1.Build-in

获取透明的Shader,修改模型材质的Shader,修改颜色参数透明度,修改材质是否为空

   /// <summary>
    /// 将游戏物体设置成透明的(包括子物体也都设置成透明的)
    /// </summary>
    /// <param name="go"></param>
    /// <param name="transparent"></param>
    /// <param name="color"></param>
    /// <param name="isSpecular"></param>
    /// <param name="removeTexture"></param>
    /// <returns></returns>
    public static bool SetTransparent(this GameObject go, Color color, bool isSpecular, bool removeTexture = false)
    {
        Renderer render = go.GetComponent<Renderer>();
        if (render == null) return false;

        Shader shader = ShaderHelper.GetTransparentShader(isSpecular);//ShaderHelper是以前Buldin时的工具,现在没什么用,里面其实就是Shader.Find()了

        for (int i = 0; i < render.materials.Length; i++)
        {
            SetTransparentMaterial(render, i, shader, color, removeTexture);
            //StardardShaderSet.SetMaterialRenderingMode(mm, RenderingMode.Transparent);
        }
        return true;
    }

    /// <summary>
    /// 修改材质,达到透明的效果
    /// </summary>
    /// <param name="render"></param>
    /// <param name="i"></param>
    /// <param name="shader"></param>
    /// <param name="color"></param>
    /// <param name="removeTexture"></param>
    private static void SetTransparentMaterial(Renderer render, int i, Shader shader, Color color, bool removeTexture)
    {
        //Material mm = new Material(render.materials[i]);
        //Material mm = render.materials[i];
        //render.materials[i] = mm;
        render.materials[i].shader = shader;
        render.materials[i].color = color;
        if (removeTexture)
        {
            render.materials[i].mainTexture = null;
        }
    }

2.URP

修改URP/Lit材质的_SurfaceType,_Mode等参数。

参考:https://answers.unity.com/questions/1608815/change-surface-type-with-lwrp.html?_ga=2.257083661.724107984.1607480798-60239732.1590568025

using UnityEngine;
 using System;
 
 public class DisplayController : MonoBehaviour
 {
     public enum SurfaceType
     {
         Opaque,
         Transparent
     }
 public enum BlendMode
 {
     Alpha,
     Premultiply,
     Additive,
     Multiply
 }
 
 public Material wallMaterial;
 
 public void ChangeWallTransparency(bool transparent)
 {
     if (transparent)
     {
         wallMaterial.SetFloat("_Surface", (float)SurfaceType.Transparent);
         wallMaterial.SetFloat("_Blend", (float)BlendMode.Alpha);
     }
     else
     {
         wallMaterial.SetFloat("_Surface", (float)SurfaceType.Opaque);
     }
     SetupMaterialBlendMode(wallMaterial);
 }
 void SetupMaterialBlendMode(Material material)
 {
     if (material == null)
         throw new ArgumentNullException("material");
     bool alphaClip = material.GetFloat("_AlphaClip") == 1;
     if (alphaClip)
         material.EnableKeyword("_ALPHATEST_ON");
     else
         material.DisableKeyword("_ALPHATEST_ON");
     SurfaceType surfaceType = (SurfaceType)material.GetFloat("_Surface");
     if (surfaceType == 0)
     {
         material.SetOverrideTag("RenderType", "");
         material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
         material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
         material.SetInt("_ZWrite", 1);
         material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
         material.renderQueue = -1;
         material.SetShaderPassEnabled("ShadowCaster", true);
     }
     else
     {
         BlendMode blendMode = (BlendMode)material.GetFloat("_Blend");
         switch (blendMode)
         {
             case BlendMode.Alpha:
                 material.SetOverrideTag("RenderType", "Transparent");
                 material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
                 material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
                 material.SetInt("_ZWrite", 0);
                 material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                 material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
                 material.SetShaderPassEnabled("ShadowCaster", false);
                 break;
             case BlendMode.Premultiply:
                 material.SetOverrideTag("RenderType", "Transparent");
                 material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
                 material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
                 material.SetInt("_ZWrite", 0);
                 material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
                 material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
                 material.SetShaderPassEnabled("ShadowCaster", false);
                 break;
             case BlendMode.Additive:
                 material.SetOverrideTag("RenderType", "Transparent");
                 material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
                 material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.One);
                 material.SetInt("_ZWrite", 0);
                 material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                 material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
                 material.SetShaderPassEnabled("ShadowCaster", false);
                 break;
             case BlendMode.Multiply:
                 material.SetOverrideTag("RenderType", "Transparent");
                 material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.DstColor);
                 material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
                 material.SetInt("_ZWrite", 0);
                 material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                 material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
                 material.SetShaderPassEnabled("ShadowCaster", false);
                 break;
         }
     }
 }
 }

3.HDRP

参考:https://forum.unity.com/threads/hdrp-make-surface-transparent-in-runtime.663025/#post-4439554

It seems like the proper thing to do is to have 2 materials, one opaque and one transparent, and switch materials on the mesh as needed.

根据查到的资料,运行过程中修改_SurfaceType,没有效果,建议给模型设置一个透明的材质,切换材质来达到透明的效果。

测试发现也可以使用将透明材质的属性全部Copy过来,一样能够透明,需要将原材质的信息备份(颜色、材质),Copy透明材质,还原原信息。

                    var color=material.GetColor("_BaseColor");
                    var texture=material.GetTexture("_BaseColorMap");

                    if(Transparent_Mat==null){
                        Transparent_Mat=Resources.Load<Material>("HDRPLit_Transparent_Double");
                    }

                    if(EnableTransparent==true){
                        Material m=GameObject.Instantiate(Transparent_Mat);
                        var materialBack=new Material(material);//备份材质,后续还原用
                        backMaterials.Add(material,materialBack);//backMaterials是个Dictionary<Material,Material>,存一下材质的备份。
                        //还原的时候 material.CopyPropertiesFromMaterial(materialBack)
                        material.CopyPropertiesFromMaterial(m);
                        material.SetColor("_BaseColor", color);
                        material.SetTexture("_BaseColorMap", texture);
                        //透明也要有金属、光滑效果的话,其他属性也要设置一下。
                    }

由于历史原因,项目中多处存在透明代码,适用于不同的渲染关系,有空找个时间统一一下,写一个统一处理三种情况的代码。

4.公司相关代码说明

TransparentHelper:最早的Build-in的透明功能

StartdarMaterialController:URP和HDRP的透明功能,调用StardarShaderMatHelper.SetMaterialRenderingMode

ModelChange:工艺流程的透明功能,调用StardarShaderMatHelper.SetMaterialRenderingMode

 

 

  • 6
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值