From b1c4a5046f4a1eafdaf7e9e9ee91fdca073f9a8b Mon Sep 17 00:00:00 2001 From: "ALIENJACK\\alien" Date: Tue, 31 Dec 2024 18:31:47 +0800 Subject: [PATCH] =?UTF-8?q?=E6=BB=A4=E9=95=9C=E5=A2=9E=E5=8A=A0=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E6=8A=BD=E8=B1=A1=E7=B1=BBFilterChainEffect,=E7=94=A8?= =?UTF-8?q?=E4=BA=8E=E6=94=AF=E6=8C=81=E5=A4=9Apass=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AppSettings/Filter/FilterChainEffect.cs | 167 ++++++++++++++++++ .../Filter/FilterChainEffect.cs.meta | 2 + .../AppSettings/Filter/FilterEffect.cs | 29 +-- 3 files changed, 186 insertions(+), 12 deletions(-) create mode 100644 AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/FilterChainEffect.cs create mode 100644 AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/FilterChainEffect.cs.meta diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/FilterChainEffect.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/FilterChainEffect.cs new file mode 100644 index 00000000..5809c4ed --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/FilterChainEffect.cs @@ -0,0 +1,167 @@ +using AxibugEmuOnline.Client; +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Rendering; + +public abstract class FilterChainEffect : FilterEffect +{ + #region SealedForDisable + protected sealed override string ShaderName => null; + protected sealed override void OnInit(Material renderMat) { } + protected sealed override void OnRenderer(Material renderMat, Texture src, RenderTexture result) + { + OnRenderer(src, result); + } + #endregion + + List m_passes = new List(); + + static int Original; + static int OriginalSize; + static int Source; + static int SourceSize; + + List m_passOutputTexNames = new List(); + + static FilterChainEffect() + { + Original = Shader.PropertyToID(nameof(Original)); + OriginalSize = Shader.PropertyToID(nameof(OriginalSize)); + Source = Shader.PropertyToID(nameof(Source)); + SourceSize = Shader.PropertyToID(nameof(SourceSize)); + } + + protected sealed override void Init() + { + DefinePasses(ref m_passes); + for (int i = 0; i < m_passes.Count; i++) + { + m_passes[i].Init(i); + m_passOutputTexNames.Add(Shader.PropertyToID(m_passes[i].NormalOutputTextureName)); + if (m_passes[i].AliasOutputTextureName != null) + m_passOutputTexNames.Add(Shader.PropertyToID(m_passes[i].AliasOutputTextureName)); + } + } + + Dictionary m_outputCaches = new Dictionary(); + private void OnRenderer(Texture input, RenderTexture finalOut) + { + m_outputCaches.Clear(); + + Vector4 originalSize = new Vector4(input.width, input.height, 1f / input.width, 1f / input.height); + + Texture lastoutput = input; + for (int i = 0; i < m_passes.Count; i++) + { + var pass = m_passes[i]; + + pass.Mat.SetTexture(Original, input); + pass.Mat.SetVector(OriginalSize, originalSize); + pass.Mat.SetTexture(Source, lastoutput); + pass.Mat.SetVector(SourceSize, new Vector4(lastoutput.width, lastoutput.height, 1f / lastoutput.width, 1f / lastoutput.height)); + foreach (var existoutput in m_passOutputTexNames) + { + if (pass.Mat.HasTexture(existoutput) && m_outputCaches.TryGetValue(existoutput, out var passOutput)) + pass.Mat.SetTexture(existoutput, passOutput); + } + + var output = pass.GetOutput(input, lastoutput, finalOut); + + m_outputCaches[pass.NormalOutputTextureName_PID] = output; + if (pass.AliasOutputTextureName != null) m_outputCaches[pass.AliasOutputTextureName_PID] = output; + + Graphics.Blit(lastoutput, output, pass.Mat); + + lastoutput = output; + } + + Graphics.Blit(lastoutput, finalOut); + } + + protected abstract void DefinePasses(ref List passes); + + public class PassDefine + { + public string ShaderName { get; private set; } + public FilterMode FilterMode { get; private set; } + public TextureWrapMode WrapMode { get; private set; } + public EnumScaleMode ScaleMode { get; private set; } + public float ScaleX { get; private set; } + public float ScaleY { get; private set; } + public string AliasOutputTextureName { get; private set; } + public int AliasOutputTextureName_PID { get; private set; } + public string NormalOutputTextureName { get; private set; } + public int NormalOutputTextureName_PID { get; private set; } + + private PassDefine() { } + + public static PassDefine Create( + string shaderName, + FilterMode filterMode = FilterMode.Point, + TextureWrapMode wrapMode = TextureWrapMode.Clamp, + EnumScaleMode scaleMode = EnumScaleMode.Source, float scaleX = 1f, float scaleY = 1f, + string outputAlias = null + ) + { + return new PassDefine() + { + ShaderName = shaderName, + FilterMode = filterMode, + WrapMode = wrapMode, + ScaleMode = scaleMode, + ScaleX = scaleX, + ScaleY = scaleY, + AliasOutputTextureName = outputAlias, + }; + } + + public int PassIndex { get; private set; } + public Material Mat { get; private set; } + internal void Init(int passIndex) + { + Mat = new Material(Shader.Find(ShaderName)); + PassIndex = passIndex; + NormalOutputTextureName = $"PassOutput{passIndex}"; + NormalOutputTextureName_PID = Shader.PropertyToID(NormalOutputTextureName); + + if (AliasOutputTextureName != null) AliasOutputTextureName_PID = Shader.PropertyToID(AliasOutputTextureName); + } + + internal RenderTexture GetOutput(Texture original, Texture source, Texture final) + { + int width = 0; + int height = 0; + switch (ScaleMode) + { + case EnumScaleMode.Viewport: + width = (int)(final.width * ScaleX); + height = (int)(final.height * ScaleY); + break; + case EnumScaleMode.Source: + width = (int)(source.width * ScaleX); + height = (int)(source.height * ScaleY); + break; + case EnumScaleMode.Absolute: + width = (int)ScaleX; + height = (int)ScaleY; + break; + } + var rt = RenderTexture.GetTemporary(width, height); + rt.wrapMode = WrapMode; + rt.filterMode = FilterMode; + + return rt; + } + } + + public enum EnumScaleMode + { + /// 以输入源为缩放基准 以分辨率作为缩放基准 以固定值定义尺寸 EditableParam => m_editableParamList.AsReadOnly(); - + private static int m_iResolutionID = Shader.PropertyToID("_iResolution"); List m_editableParamList; Material m_material; + + public IReadOnlyCollection EditableParam => m_editableParamList.AsReadOnly(); + public bool Enable { get; set; } + [Range(0.1f, 4f)] + public FloatParameter RenderScale; + public abstract string Name { get; } protected virtual float m_defaultRenderScale { get => 1f; } protected abstract string ShaderName { get; } - private static int m_iResolutionID = Shader.PropertyToID("_iResolution"); - + public FilterEffect() { RenderScale = new FloatParameter(m_defaultRenderScale); GetEditableFilterParamters(); - m_material = new Material(Shader.Find(ShaderName)); - OnInit(m_material); + + Init(); + } + + protected virtual void Init() + { + var shader = Shader.Find(ShaderName); + m_material = new Material(shader); + OnInit(m_material); } protected virtual void OnInit(Material renderMat) { }