1
0

完善RLPRO_CRT滤镜

This commit is contained in:
ALIENJACK\alien 2025-04-27 15:06:42 +08:00
parent e8fc45b006
commit fcd64a54f6
3 changed files with 230 additions and 10 deletions
AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/RLPro

View File

@ -10,25 +10,37 @@ namespace AxibugEmuOnline.Client.Filters
protected override string ShaderName => null;
#region BleedPass_Param
public FilterParameter<EnumBleedMode> BleedMode = new FilterParameter<EnumBleedMode>(EnumBleedMode.NTSCOld3Phase);
public FilterParameter<EnumBleedMode> BleedMode = EnumBleedMode.NTSCOld3Phase;
[Range(0, 15)]
public FloatParameter BleedAmount = new FloatParameter(1f);
public FloatParameter BleedAmount = 1f;
#endregion
#region CRTAperture_Param
[Range(0, 5)]
public FloatParameter GlowHalation = new FloatParameter(0.1f);
public FloatParameter GlowHalation = 0.1f;
[Range(0, 2)]
public FloatParameter GlowDifusion = new FloatParameter(0.05f);
public FloatParameter GlowDifusion = 0.05f;
[Range(0, 2)]
public FloatParameter MaskColors = new FloatParameter(2.0f);
public FloatParameter MaskColors = 2.0f;
[Range(0, 1)]
public FloatParameter MaskStrength = new FloatParameter(0.3f);
public FloatParameter MaskStrength = 0.3f;
[Range(0, 5)]
public FloatParameter GammaInput = new FloatParameter(2.4f);
public FloatParameter GammaInput = 2.4f;
[Range(0, 5)]
public FloatParameter GammaOutput = new FloatParameter(2.4f);
public FloatParameter GammaOutput = 2.4f;
[Range(0, 2.5f)]
public FloatParameter Brightness = new FloatParameter(1.5f);
public FloatParameter Brightness = 1.5f;
#endregion
#region TV_Effect_Param
public FilterParameter<EnumWrapMode> WrapMode = EnumWrapMode.SimpleWrap;
public FloatParameter maskDark = 0.5f;
public FloatParameter maskLight = 1.5f;
public FloatParameter hardScan = -8.0f;
public FloatParameter hardPix = -3.0f;
public Vector2Parameter warp = new Vector2(1.0f / 32.0f, 1.0f / 24.0f);
public Vector2Parameter res;
public FloatParameter resScale;
public FloatParameter scale;
public FloatParameter fade;
#endregion
Material m_bleedMat;
@ -39,17 +51,20 @@ namespace AxibugEmuOnline.Client.Filters
{
m_bleedMat = new Material(Shader.Find("Filter/RLPro_Bleed"));
m_crtApertureMat = new Material(Shader.Find("Filter/RLPro_CRT_Aperture"));
m_tvEffectMat = new Material(Shader.Find("Filter/RLPro_TV_Effect"));
}
protected override void OnRenderer(Material renderMat, Texture src, RenderTexture result)
{
var rt1 = BleedPass(src);
var rt2 = CRT_AperturePass(rt1);
var rt3 = TV_Effect_Pass(rt2);
Graphics.Blit(rt2, result);
Graphics.Blit(rt3, result);
RenderTexture.ReleaseTemporary(rt1);
RenderTexture.ReleaseTemporary(rt2);
RenderTexture.ReleaseTemporary(rt3);
}
private RenderTexture BleedPass(Texture src)
@ -95,6 +110,34 @@ namespace AxibugEmuOnline.Client.Filters
return rt;
}
private RenderTexture TV_Effect_Pass(Texture src)
{
var rt = RenderTexture.GetTemporary(src.width, src.height);
m_tvEffectMat.DisableKeyword("_SimpleWrap");
m_tvEffectMat.DisableKeyword("_CubicDistortion");
switch (WrapMode.GetValue())
{
case EnumWrapMode.SimpleWrap:
m_tvEffectMat.EnableKeyword("_SimpleWrap"); break;
case EnumWrapMode.CubicDistortion:
m_tvEffectMat.EnableKeyword("_CubicDistortion"); break;
}
m_tvEffectMat.SetFloat("maskDark", maskDark.GetValue());
m_tvEffectMat.SetFloat("maskLight", maskLight.GetValue());
m_tvEffectMat.SetFloat("hardScan", hardScan.GetValue());
m_tvEffectMat.SetVector("warp", warp.GetValue());
m_tvEffectMat.SetVector("res", res.GetValue());
m_tvEffectMat.SetFloat("resScale", resScale.GetValue());
m_tvEffectMat.SetFloat("scale", scale.GetValue());
m_tvEffectMat.SetFloat("fade", fade.GetValue());
Graphics.Blit(src, rt, m_tvEffectMat);
return rt;
}
public enum EnumBleedMode
{
@ -102,5 +145,11 @@ namespace AxibugEmuOnline.Client.Filters
NTSC3Phase,
NTSC2Phase,
}
public enum EnumWrapMode
{
SimpleWrap,
CubicDistortion
}
}
}

View File

@ -0,0 +1,162 @@
Shader "Filter/RLPro_TV_Effect"
{
Properties
{
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader
{
Pass
{
CGPROGRAM
#pragma shader_feature_local _SimpleWrap _CubicDistortion
#pragma vertex vert_img
#pragma fragment Frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_TexelSize;
float2 _iResolution;
float maskDark = 0.5;
float maskLight = 1.5;
float hardScan = -8.0;
float hardPix = -3.0;
float2 warp = float2(1.0 / 32.0, 1.0 / 24.0);
float2 res;
float resScale;
float scale;
float fade;
struct v2f
{
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
float3 Fetch(float2 pos, float2 off)
{
pos = floor(pos * res + off) / res;
return tex2Dlod(_MainTex, float4(pos.xy, 0, -16.0)).rgb;
}
float2 Dist(float2 pos) { pos = pos * res; return -((pos - floor(pos)) - float2(0.5, 0.5)); }
float Gaus(float pos, float scale) { return exp2(scale * pos * pos); }
float3 Horz3(float2 pos, float off)
{
float3 b = Fetch(pos, float2(-1.0, off));
float3 c = Fetch(pos, float2(0.0, off));
float3 d = Fetch(pos, float2(1.0, off));
float dst = Dist(pos).x;
float scale = hardPix;
float wb = Gaus(dst - 1.0, scale);
float wc = Gaus(dst + 0.0, scale);
float wd = Gaus(dst + 1.0, scale);
return (b * wb + c * wc + d * wd) / (wb + wc + wd);
}
float3 Horz5(float2 pos, float off)
{
float3 a = Fetch(pos, float2(-2.0, off));
float3 b = Fetch(pos, float2(-1.0, off));
float3 c = Fetch(pos, float2(0.0, off));
float3 d = Fetch(pos, float2(1.0, off));
float3 e = Fetch(pos, float2(2.0, off));
float dst = Dist(pos).x;
float scale = hardPix;
float wa = Gaus(dst - 2.0, scale);
float wb = Gaus(dst - 1.0, scale);
float wc = Gaus(dst + 0.0, scale);
float wd = Gaus(dst + 1.0, scale);
float we = Gaus(dst + 2.0, scale);
return (a * wa + b * wb + c * wc + d * wd + e * we) / (wa + wb + wc + wd + we);
}
float Scan(float2 pos, float off)
{
float dst = Dist(pos).y;
return Gaus(dst + off, hardScan);
}
float3 Tri(float2 pos)
{
float3 a = Horz3(pos, -1.0);
float3 b = Horz5(pos, 0.0);
float3 c = Horz3(pos, 1.0);
float wa = Scan(pos, -1.0);
float wb = Scan(pos, 0.0);
float wc = Scan(pos, 1.0);
return a * wa + b * wb + c * wc;
}
float2 Warp(float2 pos)
{
float2 h = pos - float2(0.5, 0.5);
float r2 = dot(h, h);
float f = 1.0 + r2 * (warp.x + warp.y * sqrt(r2));
return f * scale * h + 0.5;
}
float2 Warp1(float2 pos)
{
pos = pos * 2.0 - 1.0;
pos *= float2(1.0 + (pos.y * pos.y) * warp.x, 1.0 + (pos.x * pos.x) * warp.y);
return pos * scale + 0.5;
}
float3 Mask(float2 pos)
{
pos.x += pos.y * 3.0;
float3 mask = float3(maskDark, maskDark, maskDark);
pos.x = frac(pos.x / 6.0);
if (pos.x < 0.333)mask.r = maskLight;
else if (pos.x < 0.666)mask.g = maskLight;
else mask.b = maskLight;
return mask;
}
float4 SimpleWrapFrag(v2f i)
{
float2 uv = i.uv;
float4 col = tex2D(_MainTex,uv);
res = _ScreenParams.xy / resScale;
float2 fragCoord = uv * _ScreenParams.xy;
float4 fragColor = 0;
float2 pos = Warp1(fragCoord.xy / _ScreenParams.xy);
fragColor.rgb = Tri(pos) * Mask(fragCoord);
fragColor.a = tex2D(_MainTex,pos).a;
return lerp(col,fragColor,fade);
}
float4 CubicDistortionFrag(v2f i)
{
float2 uv = i.uv;
float4 col = tex2D(_MainTex,uv);
res = _iResolution.xy / resScale;
float2 fragCoord = uv * _ScreenParams.xy;
float4 fragColor = 0;
float2 pos = Warp(fragCoord.xy / _ScreenParams.xy);
fragColor.rgb = Tri(pos) * Mask(fragCoord);
fragColor.a = tex2D(_MainTex,pos).a;
return lerp(col,fragColor,fade);
}
float4 Frag(v2f i) : SV_Target
{
#if _SimpleWrap
return SimpleWrapFrag(i);
#else
return CubicDistortionFrag(i);
#endif
}
ENDCG
}
}
}

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: bef4d98671a3c524f9bfdba0d25e5991
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant: