From a1fe8dff21feab7f4541ab4316d4c3cd51161838 Mon Sep 17 00:00:00 2001 From: "ALIENJACK\\alien" Date: Wed, 25 Jun 2025 18:57:26 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0RealisticCRT=20shader,?= =?UTF-8?q?=E6=9D=A5=E8=87=AAgodot?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AppSettings/Filter/RealisticCRT.meta | 8 + .../Filter/RealisticCRT/RealisticCRT.cs | 60 ++++++ .../Filter/RealisticCRT/RealisticCRT.cs.meta | 2 + .../Filter/RealisticCRT/RealisticCRT.shader | 202 ++++++++++++++++++ .../RealisticCRT/RealisticCRT.shader.meta | 9 + 5 files changed, 281 insertions(+) create mode 100644 AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/RealisticCRT.meta create mode 100644 AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/RealisticCRT/RealisticCRT.cs create mode 100644 AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/RealisticCRT/RealisticCRT.cs.meta create mode 100644 AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/RealisticCRT/RealisticCRT.shader create mode 100644 AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/RealisticCRT/RealisticCRT.shader.meta diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/RealisticCRT.meta b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/RealisticCRT.meta new file mode 100644 index 00000000..2e416f2f --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/RealisticCRT.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c26c21362c8e6874e817b6f32d58fcd6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/RealisticCRT/RealisticCRT.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/RealisticCRT/RealisticCRT.cs new file mode 100644 index 00000000..f5689f20 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/RealisticCRT/RealisticCRT.cs @@ -0,0 +1,60 @@ +using Assets.Script.AppMain.Filter; +using UnityEngine; + +namespace AxibugEmuOnline.Client.Filters +{ + public class RealisticCRT : FilterEffect + { + public override string Name => nameof(RealisticCRT); + + protected override string ShaderName => "Filter/RealisticCRT"; + + [Range(0, 1)] public FloatParameter scan_line_amount = 1.0f; + [Range(0, 5)] public FloatParameter warp_amount = 0.1f; + [Range(0.0f, 0.3f)] public FloatParameter noise_amount = 0.03f; + [Range(0.0f, 1.0f)] public FloatParameter interference_amount = 0.2f; + [Range(0.0f, 1.0f)] public FloatParameter grille_amount = 0.1f; + [Range(1.0f, 5.0f)] public FloatParameter grille_size = 1.0f; + [Range(0.0f, 2.0f)] public FloatParameter vignette_amount = 0.6f; + [Range(0.0f, 1.0f)] public FloatParameter vignette_intensity = 0.4f; + [Range(0.0f, 1.0f)] public FloatParameter aberation_amount = 0.5f; + [Range(0.0f, 1.0f)] public FloatParameter roll_line_amount = 0.3f; + [Range(-8.0f, 8.0f)] public FloatParameter roll_speed = 1.0f; + [Range(-12.0f, -1.0f)] public FloatParameter scan_line_strength = -8.0f; + [Range(-4.0f, 0.0f)] public FloatParameter pixel_strength = 2.0f; + + int scan_line_amount_p = Shader.PropertyToID("scan_line_amount"); + int warp_amount_p = Shader.PropertyToID("warp_amount"); + int noise_amount_p = Shader.PropertyToID("noise_amount"); + int interference_amount_p = Shader.PropertyToID("interference_amount"); + int grille_amount_p = Shader.PropertyToID("grille_amount"); + int grille_size_p = Shader.PropertyToID("grille_size"); + int vignette_amount_p = Shader.PropertyToID("vignette_amount"); + int vignette_intensity_p = Shader.PropertyToID("vignette_intensity"); + int aberation_amount_p = Shader.PropertyToID("aberation_amount"); + int roll_line_amount_p = Shader.PropertyToID("roll_line_amount"); + int roll_speed_p = Shader.PropertyToID("roll_speed"); + int scan_line_strength_p = Shader.PropertyToID("scan_line_strength"); + int pixel_strength_p = Shader.PropertyToID("pixel_strength"); + + protected override void OnRenderer(Material renderMat, Texture src, RenderTexture result) + { + renderMat.SetFloat(scan_line_amount_p, scan_line_amount); + renderMat.SetFloat(warp_amount_p, warp_amount); + renderMat.SetFloat(noise_amount_p, noise_amount); + renderMat.SetFloat(interference_amount_p, interference_amount); + renderMat.SetFloat(grille_amount_p, grille_amount); + renderMat.SetFloat(grille_size_p, grille_size); + renderMat.SetFloat(vignette_amount_p, vignette_amount); + renderMat.SetFloat(vignette_intensity_p, vignette_intensity); + renderMat.SetFloat(aberation_amount_p, aberation_amount); + renderMat.SetFloat(roll_line_amount_p, roll_line_amount); + renderMat.SetFloat(roll_speed_p, roll_speed); + renderMat.SetFloat(scan_line_strength_p, scan_line_strength); + renderMat.SetFloat(pixel_strength_p, pixel_strength); + + + Graphics.Blit(src, result, renderMat); + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/RealisticCRT/RealisticCRT.cs.meta b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/RealisticCRT/RealisticCRT.cs.meta new file mode 100644 index 00000000..7454bd86 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/RealisticCRT/RealisticCRT.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: c976303d1b991604184e1220f40ebb31 \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/RealisticCRT/RealisticCRT.shader b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/RealisticCRT/RealisticCRT.shader new file mode 100644 index 00000000..9358fa94 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/RealisticCRT/RealisticCRT.shader @@ -0,0 +1,202 @@ +Shader "Filter/RealisticCRT" +{ + Properties + { + _MainTex ("Texture", 2D) = "white" {} + + scan_line_amount ("scan_line_amount",Range(0,1)) = 1.0 + warp_amount ("warp_amount",Range(0,5)) = 0.1 + noise_amount ("noise_amount",Range(0.0, 0.3)) = 0.03 + interference_amount ("interference_amount",Range(0.0, 1.0)) = 0.2 + grille_amount ("grille_amount",Range(0.0, 1.0)) = 0.1 + grille_size ("grille_size",Range(1.0, 5.0)) = 1.0 + vignette_amount ("vignette_amount",Range(0.0, 2.0)) = 0.6 + vignette_intensity ("vignette_intensity",Range (0.0, 1.0)) = 0.4 + aberation_amount ("aberation_amount",Range(0.0, 1.0)) = 0.5 + roll_line_amount ("roll_line_amount",Range(0.0, 1.0)) = 0.3 + roll_speed ("roll_speed",Range(-8.0, 8.0)) = 1.0 + scan_line_strength ("scan_line_strength",Range(-12.0, -1.0))= -8.0 + pixel_strength ("pixel_strength",Range(-4.0, 0.0))= -2.0 + } + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + + #include "UnityCG.cginc" + + struct v2f + { + float4 pos : POSITION; + float2 uv : TEXCOORD0; + }; + + sampler2D _MainTex; + float2 _iResolution; + + #define resolution float2(320.0,180.0) + #define PI 3.14159268 + + float scan_line_amount; + float warp_amount; + float noise_amount; + float interference_amount; + float grille_amount; + float grille_size; + float vignette_amount; + float vignette_intensity; + float aberation_amount; + float roll_line_amount; + float roll_speed; + float scan_line_strength; + float pixel_strength; + + float random(float2 uv){ + return frac(cos(uv.x * 83.4827 + uv.y * 92.2842) * 43758.5453123); + } + + float3 fetch_pixel(float2 uv, float2 off) + { + float2 pos = floor(uv * resolution + off) / resolution + float2(0.5,0.5) / resolution; + + float noise = 0.0; + if(noise_amount > 0.0){ + noise = random(pos + frac(_Time.x)) * noise_amount; + } + + if(max(abs(pos.x - 0.5), abs(pos.y - 0.5)) > 0.5){ + return float3(0.0, 0.0, 0.0); + } + + float3 clr = tex2D(_MainTex,pos).rgb + noise; + return clr; + } + + // Distance in emulated pixels to nearest texel. + float2 Dist(float2 pos){ + pos = pos * resolution; + return - ((pos - floor(pos)) - float2(0.5,0.5)); + } + + // 1D Gaussian. + float Gaus(float pos, float scale){ return exp2(scale * pos * pos); } + + // 3-tap Gaussian filter along horz line. + float3 Horz3(float2 pos, float off){ + float3 b = fetch_pixel(pos, float2(-1.0, off)); + float3 c = fetch_pixel(pos, float2( 0.0, off)); + float3 d = fetch_pixel(pos, float2( 1.0, off)); + float dst = Dist(pos).x; + + // Convert distance to weight. + float scale = pixel_strength; + float wb = Gaus(dst - 1.0, scale); + float wc = Gaus(dst + 0.0, scale); + float wd = Gaus(dst + 1.0, scale); + + // Return filtered sample. + return (b * wb + c * wc + d * wd) / (wb + wc + wd); + } + + // Return scanline weight. + float Scan(float2 pos, float off){ + float dst = Dist(pos).y; + + return Gaus(dst + off, scan_line_strength); + } + + // Allow nearest three lines to effect pixel. + float3 Tri(float2 pos){ + float3 clr = fetch_pixel(pos, float2(0.0,0.0)); + if(scan_line_amount > 0.0){ + float3 a = Horz3(pos,-1.0); + float3 b = Horz3(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); + + float3 scanlines = a * wa + b * wb + c * wc; + clr = lerp(clr, scanlines, scan_line_amount); + } + return clr; + } + + // Takes in the UV and warps the edges, creating the spherized effect + float2 warp(float2 uv){ + float2 delta = uv - 0.5; + float delta2 = dot(delta.xy, delta.xy); + float delta4 = delta2 * delta2; + float delta_offset = delta4 * warp_amount; + + float2 warped = uv + delta * delta_offset; + return (warped - 0.5) / lerp(1.0,1.2,warp_amount/5.0) + 0.5; + } + + float vignette(float2 uv){ + uv *= 1.0 - uv.xy; + float vignette = uv.x * uv.y * 15.0; + return pow(vignette, vignette_intensity * vignette_amount); + } + + float floating_mod(float a, float b){ + return a - b * floor(a/b); + } + + float3 grille(float2 uv){ + float unit = PI / 3.0; + float scale = 2.0*unit/grille_size; + float r = smoothstep(0.5, 0.8, cos(uv.x*scale - unit)); + float g = smoothstep(0.5, 0.8, cos(uv.x*scale + unit)); + float b = smoothstep(0.5, 0.8, cos(uv.x*scale + 3.0*unit)); + return lerp(float3(1.0,1.0,1.0), float3(r,g,b), grille_amount); + } + + float roll_line(float2 uv){ + float x = uv.y * 3.0 - _Time.x * roll_speed; + float f = cos(x) * cos(x * 2.35 + 1.1) * cos(x * 4.45 + 2.3); + float roll_line = smoothstep(0.5, 0.9, f); + return roll_line * roll_line_amount; + } + + fixed4 frag (v2f i) : SV_Target + { + float2 pix = _iResolution.xy*i.uv; + float2 pos = warp(i.uv); + + float tLine = 0.0; + if(roll_line_amount > 0.0){ + tLine = roll_line(pos); + } + + float2 sq_pix = floor(pos * resolution) / resolution + float2(0.5,0.5) / resolution; + if(interference_amount + roll_line_amount > 0.0){ + float interference = random(sq_pix.yy + frac(_Time.x)); + pos.x += (interference * (interference_amount + tLine * 6.0)) / resolution.x; + } + + float3 clr = Tri(pos); + if(aberation_amount > 0.0){ + float chromatic = aberation_amount + tLine * 2.0; + float2 chromatic_x = float2(chromatic,0.0) / resolution.x; + float2 chromatic_y = float2(0.0, chromatic/2.0) / resolution.y; + float r = Tri(pos - chromatic_x).r; + float g = Tri(pos + chromatic_y).g; + float b = Tri(pos + chromatic_x).b; + clr = float3(r,g,b); + } + + if(grille_amount > 0.0)clr *= grille(pix); + clr *= 1.0 + scan_line_amount * 0.6 + tLine * 3.0 + grille_amount * 2.0; + if(vignette_amount > 0.0)clr *= vignette(pos); + + return fixed4(clr,1.0); + } + ENDCG + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/RealisticCRT/RealisticCRT.shader.meta b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/RealisticCRT/RealisticCRT.shader.meta new file mode 100644 index 00000000..1830dab1 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/RealisticCRT/RealisticCRT.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 467a95e560665c641ad8a0925e03a93c +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: