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("Es.InkPainter.Fluid.HeightDrip")); height2Normal = new Material(Resources.Load("Es.InkPainter.Fluid.HeightToNormal")); height2Color = new Material(Resources.Load("Es.InkPainter.Fluid.HeightToColor")); singleColorFill = new Material(Resources.Load("Es.InkPainter.Fluid.SingleColorFill")); invertAlpha = new Material(Resources.Load("Es.InkPainter.Fluid.InvertAlpha")); canvas = GetComponent(); 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); } } } }