// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; using UnityEngine.Rendering; using WaveHarmonic.Crest.Internal; namespace WaveHarmonic.Crest { /// /// Data storage for for the Texture input mode. /// [System.Serializable] public abstract partial class TextureLodInputData : LodInputData { [Tooltip("Texture to render into the simulation.")] [@GenerateAPI] [@DecoratedField, SerializeField] internal Texture _Texture; [Tooltip("Multiplies the texture sample.\n\nThis is useful for normalized textures. The four components map to the four color/alpha components of the texture (if they exist).\n\nIf you just want to fade out the input, consider using weight instead.")] [@GenerateAPI] [@DecoratedField, SerializeField] Vector4 _Multiplier = Vector4.one; private protected abstract ComputeShader TextureShader { get; } internal override bool IsEnabled => _Texture != null; internal override bool HasHeightRange => false; internal override void RecalculateRect() { _Rect = _Input.transform.RectXZ(); } internal override void RecalculateBounds() { throw new System.NotImplementedException(); } internal override void Draw(Lod lod, Component component, CommandBuffer buffer, RenderTargetIdentifier target, int slices) { var transform = component.transform; var wrapper = new PropertyWrapperCompute(buffer, TextureShader, 0); var rotation = new Vector2(transform.localToWorldMatrix.m20, transform.localToWorldMatrix.m00).normalized; wrapper.SetVector(ShaderIDs.s_TextureSize, transform.lossyScale.XZ()); wrapper.SetVector(ShaderIDs.s_TexturePosition, transform.position.XZ()); wrapper.SetVector(ShaderIDs.s_TextureRotation, rotation); wrapper.SetVector(ShaderIDs.s_Resolution, new(_Texture.width, _Texture.height)); wrapper.SetVector(ShaderIDs.s_Multiplier, _Multiplier); wrapper.SetFloat(ShaderIDs.s_FeatherWidth, _Input.FeatherWidth); wrapper.SetTexture(ShaderIDs.s_Texture, _Texture); wrapper.SetInteger(ShaderIDs.s_Blend, (int)_Input.Blend); wrapper.SetTexture(ShaderIDs.s_Target, target); if (this is LevelTextureLodInputData height) { wrapper.SetKeyword(WaterResources.Instance.Keywords.LevelTextureCatmullRom, height._UseCatmullRomFiltering); } if (this is DirectionalTextureLodInputData data) { wrapper.SetBoolean(ShaderIDs.s_NegativeValues, data._NegativeValues); } var threads = lod.Resolution / Lod.k_ThreadGroupSize; wrapper.Dispatch(threads, threads, slices); } internal override void OnEnable() { // Empty. } internal override void OnDisable() { // Empty. } #if UNITY_EDITOR internal override void OnChange(string propertyPath, object previousValue) { } internal override bool InferMode(Component component, ref LodInputMode mode) { return false; } #endif } /// [System.Serializable] public abstract partial class DirectionalTextureLodInputData : TextureLodInputData { [Tooltip("Whether the texture supports negative values.")] [@GenerateAPI] [@DecoratedField, SerializeField] internal bool _NegativeValues; } /// partial class LevelTextureLodInputData { [Label("Filtering (High Quality)")] [Tooltip("Helps with staircase aliasing.")] [@DecoratedField, SerializeField] internal bool _UseCatmullRomFiltering; } }