using Es.InkPainter; using UnityEngine; namespace Es.WaveformProvider { [RequireComponent(typeof(Renderer))] [DisallowMultipleComponent] public class WaveConductor : MonoBehaviour { [SerializeField] public bool update = true; [Range(1f, 10f)] public int updateFrameTiming = 3; [Range(0f, 1f)] public float adjuster; [Range(0.01f, 2f)] public float stride = 1f; [Range(0.1f, 1f)] public float attenuation = 0.96f; [Range(0.01f, 0.5f)] public float propagationSpeed = 0.1f; [SerializeField] private int inputTextureSize = 512; [SerializeField] private RenderTexture output; [SerializeField] private bool debug; private static Material waveMaterial; private Texture2D init; private RenderTexture input; private RenderTexture prev; private RenderTexture prev2; private RenderTexture result; private InkCanvas inkCanvas; private Brush brush; private readonly int ShaderPropertyAdjust = Shader.PropertyToID("_RoundAdjuster"); private readonly int ShaderPropertyStride = Shader.PropertyToID("_Stride"); private readonly int ShaderPropertyAttenuation = Shader.PropertyToID("_Attenuation"); private readonly int ShaderPropertyC = Shader.PropertyToID("_C"); private readonly int ShaderPropertyInputTex = Shader.PropertyToID("_InputTex"); private readonly int ShaderPropertyPrevTex = Shader.PropertyToID("_PrevTex"); private readonly int ShaderPropertyPrev2Tex = Shader.PropertyToID("_Prev2Tex"); public RenderTexture Output { get { return output; } set { output = value; } } private Material WaveMaterial { get { if (waveMaterial == null) { waveMaterial = new Material(Resources.Load("Es.WaveformProvider.WaveProvide")); } return waveMaterial; } } private void Awake() { brush = new Brush(Texture2D.whiteTexture, 0.1f, Color.white, null, 0f, Texture2D.whiteTexture, 1f, Brush.ColorBlendType.UseBrush, Brush.NormalBlendType.UseBrush, Brush.HeightBlendType.Add); Material material = new Material(Resources.Load("Es.WaveformProvider.WaveInput")); InkCanvas.PaintSet paintSet = new InkCanvas.PaintSet("", "", "_ParallaxMap", useMainPaint: false, useNormalPaint: false, useHeightPaint: true, material); inkCanvas = base.gameObject.AddInkCanvas(paintSet); inkCanvas.hideFlags = HideFlags.HideInInspector; inkCanvas.OnInitializedAfter += delegate { paintSet.paintHeightTexture = new RenderTexture(inputTextureSize, inputTextureSize, 0, RenderTextureFormat.R8); init = new Texture2D(1, 1); init.SetPixel(0, 0, new Color(0f, 0f, 0f, 0f)); init.Apply(); input = paintSet.paintHeightTexture; prev = new RenderTexture(input.width, input.height, 0, RenderTextureFormat.R8); prev2 = new RenderTexture(input.width, input.height, 0, RenderTextureFormat.R8); result = new RenderTexture(input.width, input.height, 0, RenderTextureFormat.R8); Texture2D texture2D = new Texture2D(1, 1); texture2D.SetPixel(0, 0, new Color(0.5f, 0f, 0f, 1f)); texture2D.Apply(); Graphics.Blit(texture2D, prev); Graphics.Blit(texture2D, prev2); }; } private void OnWillRenderObject() { WaveUpdate(); } private void OnGUI() { if (debug) { int num = Screen.height / 3; GUI.Box(new Rect(0f, 0f, num, num * 3), ""); GUI.DrawTexture(new Rect(0f, 0f, num, num), input); GUI.DrawTexture(new Rect(0f, num, num, num), prev); GUI.DrawTexture(new Rect(0f, 2 * num, num, num), prev2); GUI.Box(new Rect(0f, num - 20, num, 20f), "INPUT"); GUI.Box(new Rect(0f, 2 * num - 20, num, 20f), "PREV"); GUI.Box(new Rect(0f, 3 * num - 20, num, 20f), "PREV2"); } } public void Input(Texture2D waveform, Vector2 uv, float scale, float strength = 0.1f) { brush.BrushTexture = waveform; brush.Scale = scale; brush.HeightBlend = strength; inkCanvas.PaintUVDirect(brush, uv); } public void Input(Texture2D waveform, Vector3 worldPos, float scale, float strength = 0.1f) { brush.BrushTexture = waveform; brush.Scale = scale; brush.HeightBlend = strength; inkCanvas.Paint(brush, worldPos); } public void Input(Texture2D waveform, RaycastHit hitInfo, float scale, float strength = 0.1f) { brush.BrushTexture = waveform; brush.Scale = scale; brush.HeightBlend = strength; inkCanvas.Paint(brush, hitInfo); } public void InputNearestTriangleSurface(Texture2D waveform, Vector3 worldPos, float scale, float strength = 0.1f) { brush.BrushTexture = waveform; brush.Scale = scale; brush.HeightBlend = strength; inkCanvas.PaintNearestTriangleSurface(brush, worldPos); } private void WaveUpdate() { if (update && Time.frameCount % updateFrameTiming == 0 && !(input == null) && !(output == null)) { WaveMaterial.SetFloat(ShaderPropertyAdjust, adjuster); WaveMaterial.SetFloat(ShaderPropertyStride, stride); WaveMaterial.SetFloat(ShaderPropertyAttenuation, attenuation); WaveMaterial.SetFloat(ShaderPropertyC, propagationSpeed); WaveMaterial.SetTexture(ShaderPropertyInputTex, input); WaveMaterial.SetTexture(ShaderPropertyPrevTex, prev); WaveMaterial.SetTexture(ShaderPropertyPrev2Tex, prev2); Graphics.Blit(null, result, WaveMaterial); RenderTexture renderTexture = prev2; prev2 = prev; prev = result; result = renderTexture; Graphics.Blit(init, input); Graphics.Blit(prev, output); } } } }