179 lines
6.1 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |