112 lines
4.8 KiB
C#
112 lines
4.8 KiB
C#
|
|
using UnityEngine;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 材质渲染模式助手类
|
|||
|
|
/// 用于设置材质的正确渲染模式以支持透明度
|
|||
|
|
/// </summary>
|
|||
|
|
public static class MaterialRenderModeHelper
|
|||
|
|
{
|
|||
|
|
public enum BlendMode
|
|||
|
|
{
|
|||
|
|
Opaque,
|
|||
|
|
Cutout,
|
|||
|
|
Fade, // Traditional transparency (ZWrite OFF)
|
|||
|
|
Transparent, // Physically based transparency (ZWrite OFF)
|
|||
|
|
AlphaBlendWithDepth // Alpha blend with depth write (ZWrite ON) - 解决Body显示问题
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 设置材质的渲染模式
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="material">要设置的材质</param>
|
|||
|
|
/// <param name="blendMode">渲染模式</param>
|
|||
|
|
public static void SetMaterialRenderMode(Material material, BlendMode blendMode)
|
|||
|
|
{
|
|||
|
|
switch (blendMode)
|
|||
|
|
{
|
|||
|
|
case BlendMode.Opaque:
|
|||
|
|
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.renderQueue = -1;
|
|||
|
|
break;
|
|||
|
|
case BlendMode.Cutout:
|
|||
|
|
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.renderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest;
|
|||
|
|
break;
|
|||
|
|
case BlendMode.Fade:
|
|||
|
|
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.EnableKeyword("_ALPHABLEND_ON");
|
|||
|
|
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
|
|||
|
|
material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
|
|||
|
|
break;
|
|||
|
|
case BlendMode.Transparent:
|
|||
|
|
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.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
|
|||
|
|
break;
|
|||
|
|
case BlendMode.AlphaBlendWithDepth:
|
|||
|
|
// 关键修复:保持深度写入的透明混合模式
|
|||
|
|
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
|
|||
|
|
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
|
|||
|
|
material.SetInt("_ZWrite", 1); // 保持深度写入,这样Body即使单独存在也能正确显示
|
|||
|
|
material.DisableKeyword("_ALPHATEST_ON");
|
|||
|
|
material.EnableKeyword("_ALPHABLEND_ON");
|
|||
|
|
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
|
|||
|
|
// 使用较早的渲染队列,确保在其他透明物体之前渲染
|
|||
|
|
material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Geometry + 450;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 自动检测并设置合适的渲染模式
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="material">材质</param>
|
|||
|
|
/// <param name="alpha">透明度值</param>
|
|||
|
|
public static void AutoSetRenderMode(Material material, float alpha)
|
|||
|
|
{
|
|||
|
|
if (alpha >= 1.0f)
|
|||
|
|
{
|
|||
|
|
SetMaterialRenderMode(material, BlendMode.Opaque);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
SetMaterialRenderMode(material, BlendMode.AlphaBlendWithDepth);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 专门为Body设置渲染模式
|
|||
|
|
/// 确保Body在单独显示时也能正确显示
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="material">Body材质</param>
|
|||
|
|
/// <param name="alpha">透明度值</param>
|
|||
|
|
public static void SetBodyRenderMode(Material material, float alpha)
|
|||
|
|
{
|
|||
|
|
if (alpha >= 1.0f)
|
|||
|
|
{
|
|||
|
|
SetMaterialRenderMode(material, BlendMode.Opaque);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
// 对于Body,始终使用保持深度写入的透明模式
|
|||
|
|
SetMaterialRenderMode(material, BlendMode.AlphaBlendWithDepth);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|