Files
Cielonos/Assets/OtherPlugins/GraphicsCat/Modules/LitPlus/Runtime/Experimental/LitPlusAlphaFadeController.cs
SoulliesOfficial d15957c719 更新
2025-12-17 04:19:38 -05:00

179 lines
6.1 KiB
C#

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
namespace GraphicsCat.LitPlus.Experimental
{
// Fade in/out, supports composite objects
public class LitPlusAlphaFadeController : MonoBehaviour
{
internal class PropertyID
{
readonly public static int ZWrite = Shader.PropertyToID("_ZWrite");
readonly public static int SrcBlend = Shader.PropertyToID("_SrcBlend");
readonly public static int DstBlend = Shader.PropertyToID("_DstBlend");
readonly public static int Color = Shader.PropertyToID("_BaseColor");
readonly public static int BlendMode = Shader.PropertyToID("_SURFACE_TYPE");
}
internal class MaterialInfo
{
float m_OriginalZWrite;
float m_OriginalSrcFac;
float m_OriginalDstFac;
Color m_OriginalColor;
int m_OriginalRenderQueue;
float m_OriginalBlendMode;
public float originalAlpha
{
get { return m_OriginalColor.a; }
}
public void Backup(Material material)
{
m_OriginalBlendMode = material.GetFloat(PropertyID.BlendMode);
m_OriginalZWrite = material.GetFloat(PropertyID.ZWrite);
m_OriginalSrcFac = material.GetFloat(PropertyID.SrcBlend);
m_OriginalDstFac = material.GetFloat(PropertyID.DstBlend);
m_OriginalColor = material.GetColor(PropertyID.Color);
m_OriginalRenderQueue = material.renderQueue;
}
public void Restore(Material material)
{
material.SetFloat(PropertyID.BlendMode, m_OriginalBlendMode);
switch (m_OriginalBlendMode)
{
case 0: material.EnableKeyword("_SURFACE_TYPE_OPAQUE"); break;
case 1: material.EnableKeyword("_SURFACE_TYPE_CUTOUT"); break;
}
material.renderQueue = m_OriginalRenderQueue;
material.SetFloat(PropertyID.ZWrite, m_OriginalZWrite);
material.SetFloat(PropertyID.SrcBlend, m_OriginalSrcFac);
material.SetFloat(PropertyID.DstBlend, m_OriginalDstFac);
material.SetColor(PropertyID.Color, m_OriginalColor);
}
public void OnBeginFade(Material material, float alpha)
{
// Still need to write depth, otherwise there may be confusion (e.g., hair and head)
material.SetFloat(PropertyID.ZWrite, 1);
material.SetFloat(PropertyID.SrcBlend, (int)BlendMode.SrcAlpha);
material.SetFloat(PropertyID.DstBlend, (int)BlendMode.OneMinusSrcAlpha);
var color = material.GetColor(PropertyID.Color);
color.a = alpha;
material.SetColor(PropertyID.Color, color);
material.renderQueue = (int)RenderQueue.Transparent;
material.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
}
}
[Range(0.0f, 10.0f)]
public float fadeTime = 1.0f;
Dictionary<Material, MaterialInfo> m_MaterialInfos = new Dictionary<Material, MaterialInfo>();
bool m_IsFading = false;
float m_FadeTimer = 0;
bool m_FadeInOrOut = false;
public void FadeIn()
{
Fade(true);
}
public void FadeOut()
{
Fade(false);
}
void Start()
{
CollectMaterials(); // Get all materials
}
void Update()
{
if (m_IsFading) // Alpha fade
{
m_FadeTimer += Time.deltaTime;
var lerpFac = Mathf.Min(m_FadeTimer / fadeTime, 1);
foreach (var kv in m_MaterialInfos)
{
var material = kv.Key;
var materialInfo = kv.Value;
var color = material.GetColor(PropertyID.Color);
float alphaBegin = m_FadeInOrOut ? 0 : materialInfo.originalAlpha;
float alphaEnd = m_FadeInOrOut ? materialInfo.originalAlpha : 0;
color.a = Mathf.Lerp(alphaBegin, alphaEnd, lerpFac);
material.SetColor(PropertyID.Color, color);
}
if (m_FadeTimer >= fadeTime)
{
m_IsFading = false;
OnEndFade();
}
}
}
void Fade(bool inOrOut)
{
m_IsFading = true;
m_FadeTimer = 0;
m_FadeInOrOut = inOrOut;
OnBgeinFade(inOrOut ? 0 : 1);
}
void OnBgeinFade(float alpha)
{
foreach (var kv in m_MaterialInfos)
{
var material = kv.Key;
var materialInfo = kv.Value;
materialInfo.OnBeginFade(material, alpha);
}
}
void OnEndFade()
{
foreach (var kv in m_MaterialInfos)
{
var material = kv.Key;
var materialInfo = kv.Value;
materialInfo.Restore(material);
}
}
void CollectMaterials()
{
var renderres = gameObject.GetComponentsInChildren<Renderer>(false);
foreach (var renderer in renderres)
{
// Cannot use ShareMaterials, otherwise it will affect other objects
var materials = renderer.materials;
if (materials == null)
continue;
foreach (var material in materials)
{
if (m_MaterialInfos.ContainsKey(material) == false)
{
if (material.shader.name.ToLower().IndexOf("graphicscat/litplus") != -1)
{
var info = new MaterialInfo();
info.Backup(material); // Collect original material data
m_MaterialInfos.Add(material, info);
}
}
}
}
}
}
}