using UnityEngine; namespace UltimateWater.Internal { public abstract class GpuFFT { private Texture2D _Butterfly; protected RenderTexturesCache _RenderTexturesSet; protected int _Resolution; protected int _NumButterflies; protected int _NumButterfliesPow2; protected bool _TwoChannels; private readonly bool _HighPrecision; private readonly bool _UsesUav; public Texture2D Butterfly { get { return _Butterfly; } } public int Resolution { get { return _Resolution; } } protected GpuFFT(int resolution, bool highPrecision, bool twoChannels, bool usesUAV) { _Resolution = resolution; _HighPrecision = highPrecision; _NumButterflies = (int)(Mathf.Log(resolution) / Mathf.Log(2f)); _NumButterfliesPow2 = Mathf.NextPowerOfTwo(_NumButterflies); _TwoChannels = twoChannels; _UsesUav = usesUAV; RetrieveRenderTexturesSet(); CreateTextures(); } public abstract void SetupMaterials(); public abstract void ComputeFFT(Texture tex, RenderTexture target); public virtual void Dispose() { if (_Butterfly != null) { _Butterfly.Destroy(); _Butterfly = null; } } private void CreateTextures() { CreateButterflyTexture(); } private void RetrieveRenderTexturesSet() { RenderTextureFormat format = (_TwoChannels ? ((!_HighPrecision) ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.ARGBFloat) : ((!_HighPrecision) ? RenderTextureFormat.RGHalf : RenderTextureFormat.RGFloat)); _RenderTexturesSet = RenderTexturesCache.GetCache(_Resolution << 1, _Resolution << 1, 0, format, true, _UsesUav); } protected virtual void FillButterflyTexture(Texture2D butterfly, int[][] indices, Vector2[][] weights) { float num = _Resolution << 1; Color color = default(Color); for (int i = 0; i < _NumButterflies; i++) { for (int j = 0; j < 2; j++) { int num2 = ((j != 0) ? _Resolution : 0); for (int k = 0; k < _Resolution; k++) { int num3 = _NumButterflies - i - 1; int num4 = k << 1; color.r = ((float)(indices[num3][num4] + num2) + 0.5f) / num; color.g = ((float)(indices[num3][num4 + 1] + num2) + 0.5f) / num; color.b = weights[i][k].x; color.a = weights[i][k].y; butterfly.SetPixel(num2 + k, i, color); } } } } private void CreateButterflyTexture() { _Butterfly = new Texture2D(_Resolution << 1, _NumButterfliesPow2, (!_HighPrecision) ? TextureFormat.RGBAHalf : TextureFormat.RGBAFloat, false, true) { hideFlags = HideFlags.DontSave, filterMode = FilterMode.Point, wrapMode = TextureWrapMode.Clamp }; int[][] indices; Vector2[][] weights; ButterflyFFTUtility.ComputeButterfly(_Resolution, _NumButterflies, out indices, out weights); FillButterflyTexture(_Butterfly, indices, weights); _Butterfly.Apply(); } } }