Files
2026-03-04 10:03:45 +08:00

258 lines
8.4 KiB
C#

using UnityEngine;
namespace Es.InkPainter.Effective
{
[DisallowMultipleComponent]
[RequireComponent(typeof(InkCanvas))]
public class HeightFluid : MonoBehaviour
{
private enum ColorSynthesis
{
Add = 0,
Overwrite = 1
}
[SerializeField]
private bool useMainTextureFluid = true;
[SerializeField]
private bool useNormalMapFluid = true;
[SerializeField]
private int createTextureSize = 1024;
[SerializeField]
private ColorSynthesis colorSynthesis = ColorSynthesis.Overwrite;
[SerializeField]
[Range(0f, 1f)]
private float alpha = 1f;
[SerializeField]
private Vector2 flowDirection = Vector2.up;
[SerializeField]
[Range(0f, 1f)]
private float flowingForce = 1f;
[SerializeField]
[Range(0.1f, 10f)]
private float easeOfDripping = 1f;
[SerializeField]
[Range(1f, 0f)]
private float influenceOfNormal = 1f;
[SerializeField]
[Range(0.01f, 1f)]
private float horizontalSpread = 0.01f;
[SerializeField]
private float normalScaleFactor = 1f;
[SerializeField]
[Range(0.001f, 0.999f)]
private float AdhesionBorder = 0.01f;
[SerializeField]
private bool performanceOptimize = true;
[SerializeField]
[Range(0.01f, 10f)]
private float fluidProcessStopTime = 5f;
private bool enabledFluid;
private float lastPaintedTime;
private Material heightFluid;
private Material height2Normal;
private Material height2Color;
private Material singleColorFill;
private Material invertAlpha;
private InkCanvas canvas;
private Color lastPaintedColor;
private const string COLOR_SYNTHESIS_ADD = "COLOR_SYNTHESIS_ADD";
private const string COLOR_SYNTHESIS_OVERWRITE = "COLOR_SYNTHESIS_OVERWRITE";
private void Init(InkCanvas canvas)
{
foreach (InkCanvas.PaintSet paintData in canvas.PaintDatas)
{
RenderTexture paintHeightTexture = canvas.GetPaintHeightTexture(paintData.material.name);
if (paintHeightTexture != null)
{
SingleColorFill(paintHeightTexture, Vector4.zero);
}
canvas.OnPaintStart += delegate(InkCanvas own, Brush brush)
{
if (lastPaintedColor != brush.Color)
{
lastPaintedColor = brush.Color;
StopFluid();
}
};
}
}
private void SingleColorFill(RenderTexture texture, Color color)
{
RenderTexture temporary = RenderTexture.GetTemporary(texture.width, texture.height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
singleColorFill.SetVector("_Color", color);
Graphics.Blit(texture, temporary, singleColorFill);
Graphics.Blit(temporary, texture);
RenderTexture.ReleaseTemporary(temporary);
}
private void InvertAlpha(RenderTexture texture)
{
RenderTexture temporary = RenderTexture.GetTemporary(texture.width, texture.height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
Graphics.Blit(texture, temporary, invertAlpha);
Graphics.Blit(temporary, texture);
RenderTexture.ReleaseTemporary(temporary);
}
private void EnabledFluid(InkCanvas canvas, Brush brush)
{
enabledFluid = true;
lastPaintedTime = Time.time;
brush.ColorBlending = Brush.ColorBlendType.AlphaOnly;
brush.NormalBlending = Brush.NormalBlendType.UseBrush;
brush.HeightBlending = Brush.HeightBlendType.ColorRGB_HeightA;
}
private void StopFluid()
{
foreach (InkCanvas.PaintSet paintData in canvas.PaintDatas)
{
string materialName = paintData.material.name;
RenderTexture paintHeightTexture = canvas.GetPaintHeightTexture(materialName);
if (paintHeightTexture != null)
{
InvertAlpha(paintHeightTexture);
}
}
}
private void Awake()
{
heightFluid = new Material(Resources.Load<Material>("Es.InkPainter.Fluid.HeightDrip"));
height2Normal = new Material(Resources.Load<Material>("Es.InkPainter.Fluid.HeightToNormal"));
height2Color = new Material(Resources.Load<Material>("Es.InkPainter.Fluid.HeightToColor"));
singleColorFill = new Material(Resources.Load<Material>("Es.InkPainter.Fluid.SingleColorFill"));
invertAlpha = new Material(Resources.Load<Material>("Es.InkPainter.Fluid.InvertAlpha"));
canvas = GetComponent<InkCanvas>();
canvas.OnInitializedAfter += Init;
canvas.OnPaintStart += EnabledFluid;
}
private void OnWillRenderObject()
{
if (performanceOptimize && enabledFluid && Time.time - lastPaintedTime > fluidProcessStopTime)
{
StopFluid();
enabledFluid = false;
}
if (!enabledFluid)
{
return;
}
foreach (InkCanvas.PaintSet paintData in canvas.PaintDatas)
{
string materialName = paintData.material.name;
RenderTexture renderTexture = canvas.GetPaintHeightTexture(materialName);
if (renderTexture == null)
{
RenderTexture renderTexture2 = new RenderTexture(createTextureSize, createTextureSize, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
SingleColorFill(renderTexture2, Vector4.zero);
canvas.SetPaintHeightTexture(materialName, renderTexture2);
renderTexture = renderTexture2;
paintData.material.SetFloat("_Parallax", 0f);
}
RenderTexture temporary = RenderTexture.GetTemporary(renderTexture.width, renderTexture.height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
heightFluid.SetFloat("_ScaleFactor", flowingForce);
heightFluid.SetFloat("_Viscosity", easeOfDripping);
heightFluid.SetFloat("_HorizontalSpread", horizontalSpread);
heightFluid.SetFloat("_InfluenceOfNormal", influenceOfNormal);
heightFluid.SetVector("_FlowDirection", flowDirection.normalized);
heightFluid.SetVector("_FixedColor", lastPaintedColor);
string[] shaderKeywords = heightFluid.shaderKeywords;
foreach (string keyword in shaderKeywords)
{
heightFluid.DisableKeyword(keyword);
}
switch (colorSynthesis)
{
case ColorSynthesis.Add:
heightFluid.EnableKeyword("COLOR_SYNTHESIS_ADD");
break;
default:
heightFluid.EnableKeyword("COLOR_SYNTHESIS_OVERWRITE");
break;
}
if (canvas.GetNormalTexture(materialName) != null)
{
heightFluid.SetTexture("_NormalMap", canvas.GetNormalTexture(materialName));
}
Graphics.Blit(renderTexture, temporary, heightFluid);
Graphics.Blit(temporary, renderTexture);
RenderTexture.ReleaseTemporary(temporary);
if (useMainTextureFluid)
{
RenderTexture renderTexture3 = canvas.GetPaintMainTexture(materialName);
if (renderTexture3 == null)
{
RenderTexture renderTexture4 = new RenderTexture(createTextureSize, createTextureSize, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
if (canvas.GetMainTexture(materialName) != null)
{
Graphics.Blit(canvas.GetMainTexture(materialName), renderTexture4);
}
canvas.SetPaintMainTexture(materialName, renderTexture4);
renderTexture3 = renderTexture4;
}
RenderTexture temporary2 = RenderTexture.GetTemporary(renderTexture3.width, renderTexture3.height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
height2Color.SetTexture("_ColorMap", renderTexture3);
height2Color.SetTexture("_BaseColor", canvas.GetMainTexture(materialName));
height2Color.SetFloat("_Alpha", alpha);
height2Color.SetFloat("_Border", AdhesionBorder);
Graphics.Blit(renderTexture, temporary2, height2Color);
Graphics.Blit(temporary2, renderTexture3);
RenderTexture.ReleaseTemporary(temporary2);
}
if (!useNormalMapFluid)
{
continue;
}
RenderTexture renderTexture5 = canvas.GetPaintNormalTexture(materialName);
if (renderTexture5 == null)
{
RenderTexture renderTexture6 = new RenderTexture(createTextureSize, createTextureSize, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
SingleColorFill(renderTexture6, Vector4.one * 0.5f);
paintData.material.EnableKeyword("_NORMALMAP");
if (canvas.GetNormalTexture(materialName) != null)
{
Graphics.Blit(canvas.GetNormalTexture(materialName), renderTexture6);
}
canvas.SetPaintNormalTexture(materialName, renderTexture6);
renderTexture5 = renderTexture6;
}
RenderTexture temporary3 = RenderTexture.GetTemporary(renderTexture5.width, renderTexture5.height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
height2Normal.SetTexture("_BumpMap", renderTexture5);
height2Normal.SetFloat("_NormalScaleFactor", normalScaleFactor);
height2Normal.SetFloat("_Border", AdhesionBorder);
Graphics.Blit(renderTexture, temporary3, height2Normal);
Graphics.Blit(temporary3, renderTexture5);
RenderTexture.ReleaseTemporary(temporary3);
}
}
}
}